Stack.cpp revision 8bc8bf71a52e17d483021b4c9dc8e735d9bce3ed
1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * you may not use this file except in compliance with the License. 6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * You may obtain a copy of the License at 7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See the License for the specific language governing permissions and 14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * limitations under the License. 15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 164fbba1f95b3e27bdc5f5572bb0420b5f928aa54eAndy McFadden 17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Stacks and their uses (e.g. native --> interpreted method calls). 19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See the majestic ASCII art in Stack.h. 21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "Dalvik.h" 23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "jni.h" 24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <stdlib.h> 26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <stdarg.h> 27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Initialize the interpreter stack in a new thread. 30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Currently this doesn't do much, since we don't need to zero out the 32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * stack (and we really don't want to if it was created with mmap). 33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmInitInterpStack(Thread* thread, int stackSize) 35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(thread->interpStackStart != NULL); 37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 3830bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee assert(thread->interpSave.curFrame == NULL); 39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return true; 41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We're calling an interpreted method from an internal VM function or 45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * via reflection. 46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Push a frame for an interpreted method onto the stack. This is only 48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * used when calling into interpreted code from native code. (The 49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * interpreter does its own stack frame manipulation for interp-->interp 50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * calls.) 51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The size we need to reserve is the sum of parameters, local variables, 53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * saved goodies, and outbound parameters. 54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We start by inserting a "break" frame, which ensures that the interpreter 56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * hands control back to us after the function we call returns or an 57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * uncaught exception is thrown. 58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool dvmPushInterpFrame(Thread* self, const Method* method) 60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project StackSaveArea* saveBlock; 62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project StackSaveArea* breakSaveBlock; 63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int stackReq; 64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project u1* stackPtr; 65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(!dvmIsNativeMethod(method)); 67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(!dvmIsAbstractMethod(method)); 68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stackReq = method->registersSize * 4 // params + locals 70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project + sizeof(StackSaveArea) * 2 // break frame + regular frame 71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project + method->outsSize * 4; // args to other methods 72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 7330bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee if (self->interpSave.curFrame != NULL) 7430bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee stackPtr = (u1*) SAVEAREA_FROM_FP(self->interpSave.curFrame); 75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project else 76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stackPtr = self->interpStackStart; 77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (stackPtr - stackReq < self->interpStackEnd) { 79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* not enough space */ 8099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project LOGW("Stack overflow on call to interp " 816f3c21fb026d9489e5046416bcd5a84fa8e4615bDan Bornstein "(req=%d top=%p cur=%p size=%d %s.%s)", 8230bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee stackReq, self->interpStackStart, self->interpSave.curFrame, 8399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project self->interpStackSize, method->clazz->descriptor, method->name); 846ed1a0f396a1857c31b486d3e93ee2dbeb49a6cdAndy McFadden dvmHandleStackOverflow(self, method); 85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(dvmCheckException(self)); 86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Shift the stack pointer down, leaving space for the function's 91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * args/registers and save area. 92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stackPtr -= sizeof(StackSaveArea); 94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project breakSaveBlock = (StackSaveArea*)stackPtr; 95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stackPtr -= method->registersSize * 4 + sizeof(StackSaveArea); 96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock = (StackSaveArea*) stackPtr; 97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if !defined(NDEBUG) && !defined(PAD_SAVE_AREA) 99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* debug -- memset the new stack, unless we want valgrind's help */ 100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project memset(stackPtr - (method->outsSize*4), 0xaf, stackReq); 101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef EASY_GDB 10330bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee breakSaveBlock->prevSave = 10430bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee (StackSaveArea*)FP_FROM_SAVEAREA(self->interpSave.curFrame); 105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock->prevSave = breakSaveBlock; 106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 10830bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee breakSaveBlock->prevFrame = self->interpSave.curFrame; 109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project breakSaveBlock->savedPc = NULL; // not required 110d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden breakSaveBlock->xtra.localRefCookie = 0; // not required 111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project breakSaveBlock->method = NULL; 112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock->prevFrame = FP_FROM_SAVEAREA(breakSaveBlock); 113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock->savedPc = NULL; // not required 114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock->xtra.currentPc = NULL; // not required? 115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock->method = method; 116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 11760fc806b679a3655c228b4093058c59941a49cfeDan Bornstein LOGVV("PUSH frame: old=%p new=%p (size=%d)", 11830bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee self->interpSave.curFrame, FP_FROM_SAVEAREA(saveBlock), 11930bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee (u1*)self->interpSave.curFrame - (u1*)FP_FROM_SAVEAREA(saveBlock)); 120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 12130bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee self->interpSave.curFrame = FP_FROM_SAVEAREA(saveBlock); 122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return true; 124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We're calling a JNI native method from an internal VM fuction or 128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * via reflection. This is also used to create the "fake" native-method 129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * frames at the top of the interpreted stack. 130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This actually pushes two frames; the first is a "break" frame. 132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The top frame has additional space for JNI local reference tracking. 134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmPushJNIFrame(Thread* self, const Method* method) 136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project StackSaveArea* saveBlock; 138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project StackSaveArea* breakSaveBlock; 139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int stackReq; 140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project u1* stackPtr; 141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(dvmIsNativeMethod(method)); 143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stackReq = method->registersSize * 4 // params only 145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project + sizeof(StackSaveArea) * 2; // break frame + regular frame 146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 14730bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee if (self->interpSave.curFrame != NULL) 14830bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee stackPtr = (u1*) SAVEAREA_FROM_FP(self->interpSave.curFrame); 149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project else 150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stackPtr = self->interpStackStart; 151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (stackPtr - stackReq < self->interpStackEnd) { 153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* not enough space */ 15499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project LOGW("Stack overflow on call to native " 1556f3c21fb026d9489e5046416bcd5a84fa8e4615bDan Bornstein "(req=%d top=%p cur=%p size=%d '%s')", 15630bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee stackReq, self->interpStackStart, self->interpSave.curFrame, 15799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project self->interpStackSize, method->name); 1586ed1a0f396a1857c31b486d3e93ee2dbeb49a6cdAndy McFadden dvmHandleStackOverflow(self, method); 159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(dvmCheckException(self)); 160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Shift the stack pointer down, leaving space for just the stack save 165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * area for the break frame, then shift down farther for the full frame. 166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We leave space for the method args, which are copied in later. 167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stackPtr -= sizeof(StackSaveArea); 169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project breakSaveBlock = (StackSaveArea*)stackPtr; 170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stackPtr -= method->registersSize * 4 + sizeof(StackSaveArea); 171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock = (StackSaveArea*) stackPtr; 172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if !defined(NDEBUG) && !defined(PAD_SAVE_AREA) 174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* debug -- memset the new stack */ 175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project memset(stackPtr, 0xaf, stackReq); 176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef EASY_GDB 17830bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee if (self->interpSave.curFrame == NULL) 179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project breakSaveBlock->prevSave = NULL; 180fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro else { 18130bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee void* fp = FP_FROM_SAVEAREA(self->interpSave.curFrame); 182fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro breakSaveBlock->prevSave = (StackSaveArea*)fp; 183fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro } 184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock->prevSave = breakSaveBlock; 185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 18730bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee breakSaveBlock->prevFrame = self->interpSave.curFrame; 188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project breakSaveBlock->savedPc = NULL; // not required 189d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden breakSaveBlock->xtra.localRefCookie = 0; // not required 190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project breakSaveBlock->method = NULL; 191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock->prevFrame = FP_FROM_SAVEAREA(breakSaveBlock); 192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock->savedPc = NULL; // not required 193d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden saveBlock->xtra.localRefCookie = self->jniLocalRefTable.segmentState.all; 194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock->method = method; 195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 19660fc806b679a3655c228b4093058c59941a49cfeDan Bornstein LOGVV("PUSH JNI frame: old=%p new=%p (size=%d)", 19730bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee self->interpSave.curFrame, FP_FROM_SAVEAREA(saveBlock), 19830bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee (u1*)self->interpSave.curFrame - (u1*)FP_FROM_SAVEAREA(saveBlock)); 199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 20030bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee self->interpSave.curFrame = FP_FROM_SAVEAREA(saveBlock); 201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return true; 203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This is used by the JNI PushLocalFrame call. We push a new frame onto 207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the stack that has no ins, outs, or locals, and no break frame above it. 208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * It's strictly used for tracking JNI local refs, and will be popped off 209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * by dvmPopFrame if it's not removed explicitly. 210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmPushLocalFrame(Thread* self, const Method* method) 212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project StackSaveArea* saveBlock; 214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int stackReq; 215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project u1* stackPtr; 216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(dvmIsNativeMethod(method)); 218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stackReq = sizeof(StackSaveArea); // regular frame 220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 22130bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee assert(self->interpSave.curFrame != NULL); 22230bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee stackPtr = (u1*) SAVEAREA_FROM_FP(self->interpSave.curFrame); 223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (stackPtr - stackReq < self->interpStackEnd) { 225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* not enough space; let JNI throw the exception */ 22699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project LOGW("Stack overflow on PushLocal " 2276f3c21fb026d9489e5046416bcd5a84fa8e4615bDan Bornstein "(req=%d top=%p cur=%p size=%d '%s')", 22830bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee stackReq, self->interpStackStart, self->interpSave.curFrame, 22999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project self->interpStackSize, method->name); 2306ed1a0f396a1857c31b486d3e93ee2dbeb49a6cdAndy McFadden dvmHandleStackOverflow(self, method); 231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(dvmCheckException(self)); 232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Shift the stack pointer down, leaving space for just the stack save 237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * area for the break frame, then shift down farther for the full frame. 238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stackPtr -= sizeof(StackSaveArea); 240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock = (StackSaveArea*) stackPtr; 241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if !defined(NDEBUG) && !defined(PAD_SAVE_AREA) 243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* debug -- memset the new stack */ 244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project memset(stackPtr, 0xaf, stackReq); 245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef EASY_GDB 24730bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee saveBlock->prevSave = 24830bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee (StackSaveArea*)FP_FROM_SAVEAREA(self->interpSave.curFrame); 249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 25130bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee saveBlock->prevFrame = self->interpSave.curFrame; 252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock->savedPc = NULL; // not required 253d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden saveBlock->xtra.localRefCookie = self->jniLocalRefTable.segmentState.all; 254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock->method = method; 255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 25660fc806b679a3655c228b4093058c59941a49cfeDan Bornstein LOGVV("PUSH JNI local frame: old=%p new=%p (size=%d)", 25730bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee self->interpSave.curFrame, FP_FROM_SAVEAREA(saveBlock), 25830bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee (u1*)self->interpSave.curFrame - (u1*)FP_FROM_SAVEAREA(saveBlock)); 259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 26030bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee self->interpSave.curFrame = FP_FROM_SAVEAREA(saveBlock); 261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return true; 263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Pop one frame pushed on by JNI PushLocalFrame. 267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If we've gone too far, the previous frame is either a break frame or 269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * an interpreted frame. Either way, the method pointer won't match. 270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmPopLocalFrame(Thread* self) 272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 27330bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee StackSaveArea* saveBlock = SAVEAREA_FROM_FP(self->interpSave.curFrame); 274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 27530bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee assert(!dvmIsBreakFrame((u4*)self->interpSave.curFrame)); 276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (saveBlock->method != SAVEAREA_FROM_FP(saveBlock->prevFrame)->method) { 277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The previous frame doesn't have the same method pointer -- we've 279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * been asked to pop too much. 280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 281fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro assert(dvmIsBreakFrame((u4*)saveBlock->prevFrame) || 282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project !dvmIsNativeMethod( 283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project SAVEAREA_FROM_FP(saveBlock->prevFrame)->method)); 284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 28760fc806b679a3655c228b4093058c59941a49cfeDan Bornstein LOGVV("POP JNI local frame: removing %s, now %s", 288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock->method->name, 289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project SAVEAREA_FROM_FP(saveBlock->prevFrame)->method->name); 290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmPopJniLocals(self, saveBlock); 29130bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee self->interpSave.curFrame = saveBlock->prevFrame; 292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return true; 294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Pop a frame we added. There should be one method frame and one break 298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * frame. 299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If JNI Push/PopLocalFrame calls were mismatched, we might end up 301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * popping multiple method frames before we find the break. 302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns "false" if there was no frame to pop. 304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool dvmPopFrame(Thread* self) 306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project StackSaveArea* saveBlock; 308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 30930bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee if (self->interpSave.curFrame == NULL) 310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 31230bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee saveBlock = SAVEAREA_FROM_FP(self->interpSave.curFrame); 31330bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee assert(!dvmIsBreakFrame((u4*)self->interpSave.curFrame)); 314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Remove everything up to the break frame. If this was a call into 317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * native code, pop the JNI local references table. 318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project while (saveBlock->prevFrame != NULL && saveBlock->method != NULL) { 320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* probably a native->native JNI call */ 321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (dvmIsNativeMethod(saveBlock->method)) { 32360fc806b679a3655c228b4093058c59941a49cfeDan Bornstein LOGVV("Popping JNI stack frame for %s.%s%s", 324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock->method->clazz->descriptor, 325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock->method->name, 326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project (SAVEAREA_FROM_FP(saveBlock->prevFrame)->method == NULL) ? 327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "" : " (JNI local)"); 328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmPopJniLocals(self, saveBlock); 329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveBlock = SAVEAREA_FROM_FP(saveBlock->prevFrame); 332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (saveBlock->method != NULL) { 33460fc806b679a3655c228b4093058c59941a49cfeDan Bornstein LOGE("PopFrame missed the break"); 335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(false); 336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmAbort(); // stack trashed -- nowhere to go in this thread 337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 33960fc806b679a3655c228b4093058c59941a49cfeDan Bornstein LOGVV("POP frame: cur=%p new=%p", 34030bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee self->interpSave.curFrame, saveBlock->prevFrame); 341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 34230bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee self->interpSave.curFrame = saveBlock->prevFrame; 343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return true; 344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Common code for dvmCallMethodV/A and dvmInvokeMethod. 348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 34930bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee * Pushes a call frame on, advancing self->interpSave.curFrame. 350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic ClassObject* callPrep(Thread* self, const Method* method, Object* obj, 352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project bool checkAccess) 353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ClassObject* clazz; 355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifndef NDEBUG 357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (self->status != THREAD_RUNNING) { 35860fc806b679a3655c228b4093058c59941a49cfeDan Bornstein LOGW("threadid=%d: status=%d on call to %s.%s -", 35999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project self->threadId, self->status, 360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project method->clazz->descriptor, method->name); 361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(self != NULL); 365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(method != NULL); 366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (obj != NULL) 368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project clazz = obj->clazz; 369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project else 370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project clazz = method->clazz; 371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project IF_LOGVV() { 373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project char* desc = dexProtoCopyMethodDescriptor(&method->prototype); 37460fc806b679a3655c228b4093058c59941a49cfeDan Bornstein LOGVV("thread=%d native code calling %s.%s %s", self->threadId, 375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project clazz->descriptor, method->name, desc); 376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project free(desc); 377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (checkAccess) { 380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* needed for java.lang.reflect.Method.invoke */ 38130bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee if (!dvmCheckMethodAccess(dvmGetCaller2Class(self->interpSave.curFrame), 382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project method)) 383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* note this throws IAException, not IAError */ 385d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein dvmThrowIllegalAccessException("access to method denied"); 386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return NULL; 387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Push a call frame on. If there isn't enough room for ins, locals, 392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * outs, and the saved state, it will throw an exception. 393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 39430bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee * This updates self->interpSave.curFrame. 395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (dvmIsNativeMethod(method)) { 397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* native code calling native code the hard way */ 398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!dvmPushJNIFrame(self, method)) { 399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(dvmCheckException(self)); 400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return NULL; 401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* native code calling interpreted code */ 404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!dvmPushInterpFrame(self, method)) { 405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(dvmCheckException(self)); 406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return NULL; 407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return clazz; 411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Issue a method call. 415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Pass in NULL for "obj" on calls to static methods. 417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (Note this can't be inlined because it takes a variable number of args.) 419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmCallMethod(Thread* self, const Method* method, Object* obj, 421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project JValue* pResult, ...) 422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project va_list args; 424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project va_start(args, pResult); 425d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden dvmCallMethodV(self, method, obj, false, pResult, args); 426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project va_end(args); 427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Issue a method call with a variable number of arguments. We process 431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the contents of "args" by scanning the method signature. 432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Pass in NULL for "obj" on calls to static methods. 434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We don't need to take the class as an argument because, in Dalvik, 436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * we don't need to worry about static synchronized methods. 437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmCallMethodV(Thread* self, const Method* method, Object* obj, 439d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden bool fromJni, JValue* pResult, va_list args) 440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const char* desc = &(method->shorty[1]); // [0] is the return type. 442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int verifyCount = 0; 443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ClassObject* clazz; 444f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project u4* ins; 445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project clazz = callPrep(self, method, obj, false); 447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (clazz == NULL) 448f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return; 449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* "ins" for new frame start at frame pointer plus locals */ 45130bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee ins = ((u4*)self->interpSave.curFrame) + 45230bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee (method->registersSize - method->insSize); 453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 45460fc806b679a3655c228b4093058c59941a49cfeDan Bornstein //LOGD(" FP is %p, INs live at >= %p", self->interpSave.curFrame, ins); 455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* put "this" pointer into in0 if appropriate */ 457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!dvmIsStaticMethod(method)) { 458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef WITH_EXTRA_OBJECT_VALIDATION 4598bc8bf71a52e17d483021b4c9dc8e735d9bce3edElliott Hughes assert(obj != NULL && dvmIsHeapAddress(obj)); 460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *ins++ = (u4) obj; 462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project verifyCount++; 463f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 464f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 4650083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden JNIEnv* env = self->jniEnv; 466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project while (*desc != '\0') { 467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project switch (*(desc++)) { 468f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case 'D': case 'J': { 469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project u8 val = va_arg(args, u8); 470f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project memcpy(ins, &val, 8); // EABI prevents direct store 471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ins += 2; 472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project verifyCount += 2; 473f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 474f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case 'F': { 476f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* floats were normalized to doubles; convert back */ 477f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project float f = (float) va_arg(args, double); 478f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *ins++ = dvmFloatToU4(f); 479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project verifyCount++; 480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 481f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 482f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case 'L': { /* 'shorty' descr uses L for all refs, incl array */ 4831813ab265f691e93401c7307c0b34247842ab35eCarl Shapiro void* arg = va_arg(args, void*); 4848bc8bf71a52e17d483021b4c9dc8e735d9bce3edElliott Hughes assert(obj == NULL || dvmIsHeapAddress(obj)); 4851813ab265f691e93401c7307c0b34247842ab35eCarl Shapiro jobject argObj = reinterpret_cast<jobject>(arg); 486d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden if (fromJni) 487d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden *ins++ = (u4) dvmDecodeIndirectRef(env, argObj); 488d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden else 489d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden *ins++ = (u4) argObj; 490f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project verifyCount++; 491f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 492f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 493f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project default: { 4940083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden /* Z B C S I -- all passed as 32-bit integers */ 495f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *ins++ = va_arg(args, u4); 496f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project verifyCount++; 497f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 498f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 499f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 500f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 501f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 502f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifndef NDEBUG 503f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (verifyCount != method->insSize) { 50460fc806b679a3655c228b4093058c59941a49cfeDan Bornstein LOGE("Got vfycount=%d insSize=%d for %s.%s", verifyCount, 505f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project method->insSize, clazz->descriptor, method->name); 506f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(false); 507f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 508f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 509f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 510f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 511f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project //dvmDumpThreadStack(dvmThreadSelf()); 512f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 513f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (dvmIsNativeMethod(method)) { 51499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project TRACE_METHOD_ENTER(self, method); 515f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 516f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Because we leave no space for local variables, "curFrame" points 517f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * directly at the method arguments. 518f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 51930bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee (*method->nativeFunc)((u4*)self->interpSave.curFrame, pResult, 52030bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee method, self); 52199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project TRACE_METHOD_EXIT(self, method); 522f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 523f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmInterpret(self, method, pResult); 524f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 525f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 526e3c01dac83e6eea7f82fe81ed89cfbdd9791dbc9Carl Shapiro#ifndef NDEBUG 527f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail: 528e3c01dac83e6eea7f82fe81ed89cfbdd9791dbc9Carl Shapiro#endif 529f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmPopFrame(self); 530f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 531f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 532f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 533f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Issue a method call with arguments provided in an array. We process 534f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the contents of "args" by scanning the method signature. 535f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 536f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The values were likely placed into an uninitialized jvalue array using 537f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the field specifiers, which means that sub-32-bit fields (e.g. short, 538f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * boolean) may not have 32 or 64 bits of valid data. This is different 539f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * from the varargs invocation where the C compiler does a widening 540f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * conversion when calling a function. As a result, we have to be a 541f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * little more precise when pulling stuff out. 5428e5c78470229fd2f5474574081eaa4a2286aafeaAndy McFadden * 5438e5c78470229fd2f5474574081eaa4a2286aafeaAndy McFadden * "args" may be NULL if the method has no arguments. 544f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 545f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmCallMethodA(Thread* self, const Method* method, Object* obj, 546d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden bool fromJni, JValue* pResult, const jvalue* args) 547f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 548f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const char* desc = &(method->shorty[1]); // [0] is the return type. 549f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int verifyCount = 0; 550f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ClassObject* clazz; 551f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project u4* ins; 552f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 553f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project clazz = callPrep(self, method, obj, false); 554f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (clazz == NULL) 555f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return; 556f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 557f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* "ins" for new frame start at frame pointer plus locals */ 55830bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee ins = ((u4*)self->interpSave.curFrame) + 55930bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee (method->registersSize - method->insSize); 560f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 561f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* put "this" pointer into in0 if appropriate */ 562f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!dvmIsStaticMethod(method)) { 563f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(obj != NULL); 5640083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden *ins++ = (u4) obj; /* obj is a "real" ref */ 565f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project verifyCount++; 566f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 567f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 5680083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden JNIEnv* env = self->jniEnv; 569f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project while (*desc != '\0') { 5700083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden switch (*desc++) { 5710083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden case 'D': /* 64-bit quantity; have to use */ 5720083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden case 'J': /* memcpy() in case of mis-alignment */ 5730083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden memcpy(ins, &args->j, 8); 5740083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden ins += 2; 5750083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden verifyCount++; /* this needs an extra push */ 5760083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden break; 5770083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden case 'L': /* includes array refs */ 578d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden if (fromJni) 579d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden *ins++ = (u4) dvmDecodeIndirectRef(env, args->l); 580d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden else 581d5ab726b65d7271be261864c7e224fb90bfe06e0Andy McFadden *ins++ = (u4) args->l; 5820083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden break; 5830083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden case 'F': 5840083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden case 'I': 5850083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden *ins++ = args->i; /* full 32 bits */ 5860083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden break; 5870083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden case 'S': 5880083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden *ins++ = args->s; /* 16 bits, sign-extended */ 5890083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden break; 5900083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden case 'C': 5910083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden *ins++ = args->c; /* 16 bits, unsigned */ 5920083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden break; 5930083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden case 'B': 5940083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden *ins++ = args->b; /* 8 bits, sign-extended */ 5950083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden break; 5960083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden case 'Z': 5970083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden *ins++ = args->z; /* 8 bits, zero or non-zero */ 5980083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden break; 5990083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden default: 60060fc806b679a3655c228b4093058c59941a49cfeDan Bornstein LOGE("Invalid char %c in short signature of %s.%s", 6010083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden *(desc-1), clazz->descriptor, method->name); 6020083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden assert(false); 6030083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden goto bail; 604f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 6050083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden 6060083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden verifyCount++; 6070083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden args++; 608f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 609f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 610f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifndef NDEBUG 611f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (verifyCount != method->insSize) { 61260fc806b679a3655c228b4093058c59941a49cfeDan Bornstein LOGE("Got vfycount=%d insSize=%d for %s.%s", verifyCount, 613f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project method->insSize, clazz->descriptor, method->name); 614f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(false); 615f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 616f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 617f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 618f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 619f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (dvmIsNativeMethod(method)) { 62099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project TRACE_METHOD_ENTER(self, method); 621f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 622f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Because we leave no space for local variables, "curFrame" points 623f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * directly at the method arguments. 624f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 62530bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee (*method->nativeFunc)((u4*)self->interpSave.curFrame, pResult, 62630bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee method, self); 62799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project TRACE_METHOD_EXIT(self, method); 628f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 629f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmInterpret(self, method, pResult); 630f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 631f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 632f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail: 633f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmPopFrame(self); 634f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 635f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 636b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughesstatic void throwArgumentTypeMismatch(int argIndex, ClassObject* expected, DataObject* arg) { 637b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes std::string expectedClassName(dvmHumanReadableDescriptor(expected->descriptor)); 638b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes std::string actualClassName; 639b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes if (arg != NULL) { 640fe7f2b3920bf5d66eda262e643245b03df3e57c8Elliott Hughes actualClassName = dvmHumanReadableType(arg); 641b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes } else { 642b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes actualClassName = "null"; 643b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes } 644b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes dvmThrowExceptionFmt(gDvm.exIllegalArgumentException, "argument %d should have type %s, got %s", 645b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes argIndex + 1, expectedClassName.c_str(), actualClassName.c_str()); 646be88d8aa9753657566cca479609b4f79d095ad42Elliott Hughes} 647be88d8aa9753657566cca479609b4f79d095ad42Elliott Hughes 648f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 649f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Invoke a method, using the specified arguments and return type, through 650f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * one of the reflection interfaces. Could be a virtual or direct method 651f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (including constructors). Used for reflection. 652f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 653f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Deals with boxing/unboxing primitives and performs widening conversions. 654f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 655f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "invokeObj" will be null for a static method. 656f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 657f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If the invocation returns with an exception raised, we have to wrap it. 658f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 659f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectObject* dvmInvokeMethod(Object* obj, const Method* method, 660f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ArrayObject* argList, ArrayObject* params, ClassObject* returnType, 661f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project bool noAccessCheck) 662f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 663f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ClassObject* clazz; 664f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Object* retObj = NULL; 665f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Thread* self = dvmThreadSelf(); 666f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project s4* ins; 667f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int verifyCount, argListLength; 668f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project JValue retval; 669be420e7ce02692164617fab07facb514147abaa8Andy McFadden bool needPop = false; 670f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 671f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* verify arg count */ 672f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (argList != NULL) 673f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project argListLength = argList->length; 674f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project else 675f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project argListLength = 0; 676f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (argListLength != (int) params->length) { 6770b8b293f228b3d341054bc1fad8a92d6e533b4ddDan Bornstein dvmThrowExceptionFmt(gDvm.exIllegalArgumentException, 678be88d8aa9753657566cca479609b4f79d095ad42Elliott Hughes "wrong number of arguments; expected %d, got %d", 679f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project params->length, argListLength); 680f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return NULL; 681f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 682f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 683f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project clazz = callPrep(self, method, obj, !noAccessCheck); 684f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (clazz == NULL) 685f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return NULL; 686be420e7ce02692164617fab07facb514147abaa8Andy McFadden needPop = true; 687f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 688f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* "ins" for new frame start at frame pointer plus locals */ 68930bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee ins = ((s4*)self->interpSave.curFrame) + 69030bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee (method->registersSize - method->insSize); 691f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project verifyCount = 0; 692f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 69360fc806b679a3655c228b4093058c59941a49cfeDan Bornstein //LOGD(" FP is %p, INs live at >= %p", self->interpSave.curFrame, ins); 694f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 695f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* put "this" pointer into in0 if appropriate */ 696f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!dvmIsStaticMethod(method)) { 697f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(obj != NULL); 698f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *ins++ = (s4) obj; 699f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project verifyCount++; 700f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 701f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 702f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 703f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Copy the args onto the stack. Primitive types are converted when 704f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * necessary, and object types are verified. 705f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 7061813ab265f691e93401c7307c0b34247842ab35eCarl Shapiro DataObject** args = (DataObject**)(void*)argList->contents; 7071813ab265f691e93401c7307c0b34247842ab35eCarl Shapiro ClassObject** types = (ClassObject**)(void*)params->contents; 7081813ab265f691e93401c7307c0b34247842ab35eCarl Shapiro for (int i = 0; i < argListLength; i++) { 7091813ab265f691e93401c7307c0b34247842ab35eCarl Shapiro int width = dvmConvertArgument(*args++, *types++, ins); 710f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (width < 0) { 711f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmPopFrame(self); // throw wants to pull PC out of stack 712be420e7ce02692164617fab07facb514147abaa8Andy McFadden needPop = false; 713be88d8aa9753657566cca479609b4f79d095ad42Elliott Hughes throwArgumentTypeMismatch(i, *(types-1), *(args-1)); 714be420e7ce02692164617fab07facb514147abaa8Andy McFadden goto bail; 715f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 716f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 717f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ins += width; 718f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project verifyCount += width; 719f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 720f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 721c4ae06fe78cffa815225f9bcd26c19e6714db572Andy McFadden#ifndef NDEBUG 722f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (verifyCount != method->insSize) { 72360fc806b679a3655c228b4093058c59941a49cfeDan Bornstein LOGE("Got vfycount=%d insSize=%d for %s.%s", verifyCount, 724f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project method->insSize, clazz->descriptor, method->name); 725f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(false); 726f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 727f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 728c4ae06fe78cffa815225f9bcd26c19e6714db572Andy McFadden#endif 729f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 730f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (dvmIsNativeMethod(method)) { 73199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project TRACE_METHOD_ENTER(self, method); 732f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 733f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Because we leave no space for local variables, "curFrame" points 734f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * directly at the method arguments. 735f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 73630bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee (*method->nativeFunc)((u4*)self->interpSave.curFrame, &retval, 73730bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee method, self); 73899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project TRACE_METHOD_EXIT(self, method); 739f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 740f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmInterpret(self, method, &retval); 741f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 742f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 743f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 744be420e7ce02692164617fab07facb514147abaa8Andy McFadden * Pop the frame immediately. The "wrap" calls below can cause 745be420e7ce02692164617fab07facb514147abaa8Andy McFadden * allocations, and we don't want the GC to walk the now-dead frame. 746be420e7ce02692164617fab07facb514147abaa8Andy McFadden */ 747be420e7ce02692164617fab07facb514147abaa8Andy McFadden dvmPopFrame(self); 748be420e7ce02692164617fab07facb514147abaa8Andy McFadden needPop = false; 749be420e7ce02692164617fab07facb514147abaa8Andy McFadden 750be420e7ce02692164617fab07facb514147abaa8Andy McFadden /* 751f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If an exception is raised, wrap and replace. This is necessary 752f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * because the invoked method could have thrown a checked exception 753f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * that the caller wasn't prepared for. 754f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 755f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We might be able to do this up in the interpreted code, but that will 756f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * leave us with a shortened stack trace in the top-level exception. 757f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 758f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (dvmCheckException(self)) { 759f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmWrapException("Ljava/lang/reflect/InvocationTargetException;"); 760f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 761f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 762f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If this isn't a void method or constructor, convert the return type 763f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * to an appropriate object. 764f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 765f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We don't do this when an exception is raised because the value 766f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * in "retval" is undefined. 767f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 768f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (returnType != NULL) { 769c4ae06fe78cffa815225f9bcd26c19e6714db572Andy McFadden retObj = (Object*)dvmBoxPrimitive(retval, returnType); 770f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmReleaseTrackedAlloc(retObj, NULL); 771f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 772f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 773f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 774f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail: 775be420e7ce02692164617fab07facb514147abaa8Andy McFadden if (needPop) { 776be420e7ce02692164617fab07facb514147abaa8Andy McFadden dvmPopFrame(self); 777be420e7ce02692164617fab07facb514147abaa8Andy McFadden } 778f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return retObj; 779f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 780f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 781d862faa2ceae186da5518607505eb942d634ced9Carl Shapirostruct LineNumFromPcContext { 782f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project u4 address; 783f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project u4 lineNum; 784d862faa2ceae186da5518607505eb942d634ced9Carl Shapiro}; 785f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 786f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic int lineNumForPcCb(void *cnxt, u4 address, u4 lineNum) 787f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 788f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LineNumFromPcContext *pContext = (LineNumFromPcContext *)cnxt; 789f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 790de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro // We know that this callback will be called in 791f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // ascending address order, so keep going until we find 792f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // a match or we've just gone past it. 793f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 794f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (address > pContext->address) { 795f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // The line number from the previous positions callback 796f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // wil be the final result. 797f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return 1; 798f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 799f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 800f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pContext->lineNum = lineNum; 801f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 802f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return (address == pContext->address) ? 1 : 0; 803f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 804f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 805f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 806f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Determine the source file line number based on the program counter. 807f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "pc" is an offset, in 16-bit units, from the start of the method's code. 808f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 809f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns -1 if no match was found (possibly because the source files were 810f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * compiled without "-g", so no line number information is present). 811f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns -2 for native methods (as expected in exception traces). 812f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 813f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint dvmLineNumFromPC(const Method* method, u4 relPc) 814f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 815f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const DexCode* pDexCode = dvmGetMethodCode(method); 816f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 817f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (pDexCode == NULL) { 818f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (dvmIsNativeMethod(method) && !dvmIsAbstractMethod(method)) 819f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return -2; 820f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return -1; /* can happen for abstract method stub */ 821f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 822f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 823f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LineNumFromPcContext context; 824f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project memset(&context, 0, sizeof(context)); 825f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project context.address = relPc; 826f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // A method with no line number info should return -1 827f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project context.lineNum = -1; 828f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 829f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dexDecodeDebugInfo(method->clazz->pDvmDex->pDexFile, pDexCode, 830f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project method->clazz->descriptor, 831f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project method->prototype.protoIdx, 832f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project method->accessFlags, 833f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project lineNumForPcCb, NULL, &context); 834de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro 835f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return context.lineNum; 836f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 837f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 838f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 839f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Compute the frame depth. 840f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 841f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Excludes "break" frames. 842f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 843f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint dvmComputeExactFrameDepth(const void* fp) 844f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 845f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int count = 0; 846f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 847f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for ( ; fp != NULL; fp = SAVEAREA_FROM_FP(fp)->prevFrame) { 848fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro if (!dvmIsBreakFrame((u4*)fp)) 849f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project count++; 850f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 851f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 852f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return count; 853f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 854f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 855f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 856f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Compute the "vague" frame depth, which is just a pointer subtraction. 857f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The result is NOT an overly generous assessment of the number of 858f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * frames; the only meaningful use is to compare against the result of 859f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * an earlier invocation. 860f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 861f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Useful for implementing single-step debugger modes, which may need to 862f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * call this for every instruction. 863f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 864f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint dvmComputeVagueFrameDepth(Thread* thread, const void* fp) 865f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 866f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const u1* interpStackStart = thread->interpStackStart; 867f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 868e3c01dac83e6eea7f82fe81ed89cfbdd9791dbc9Carl Shapiro assert((u1*) fp >= interpStackStart - thread->interpStackSize); 869e3c01dac83e6eea7f82fe81ed89cfbdd9791dbc9Carl Shapiro assert((u1*) fp < interpStackStart); 870f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return interpStackStart - (u1*) fp; 871f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 872f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 873f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 874f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get the calling frame. Pass in the current fp. 875f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 876f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Skip "break" frames and reflection invoke frames. 877f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 878f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid* dvmGetCallerFP(const void* curFrame) 879f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 880f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project void* caller = SAVEAREA_FROM_FP(curFrame)->prevFrame; 881f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project StackSaveArea* saveArea; 882f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 883f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectretry: 884fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro if (dvmIsBreakFrame((u4*)caller)) { 885f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* pop up one more */ 886f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project caller = SAVEAREA_FROM_FP(caller)->prevFrame; 887f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (caller == NULL) 888f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return NULL; /* hit the top */ 889f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 890f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 891f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If we got here by java.lang.reflect.Method.invoke(), we don't 892f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * want to return Method's class loader. Shift up one and try 893f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * again. 894f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 895f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveArea = SAVEAREA_FROM_FP(caller); 896f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (dvmIsReflectionMethod(saveArea->method)) { 897f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project caller = saveArea->prevFrame; 898f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(caller != NULL); 899f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto retry; 900f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 901f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 902f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 903f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return caller; 904f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 905f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 906f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 907f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get the caller's class. Pass in the current fp. 908f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 909f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This is used by e.g. java.lang.Class. 910f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 911f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectClassObject* dvmGetCallerClass(const void* curFrame) 912f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 913f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project void* caller; 914f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 915f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project caller = dvmGetCallerFP(curFrame); 916f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (caller == NULL) 917f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return NULL; 918f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 919f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return SAVEAREA_FROM_FP(caller)->method->clazz; 920f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 921f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 922f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 923f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get the caller's caller's class. Pass in the current fp. 924f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 925f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This is used by e.g. java.lang.Class, which wants to know about the 926f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * class loader of the method that called it. 927f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 928f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectClassObject* dvmGetCaller2Class(const void* curFrame) 929f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 930f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project void* caller = SAVEAREA_FROM_FP(curFrame)->prevFrame; 931f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project void* callerCaller; 932f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 933f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* at the top? */ 93430bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee if (dvmIsBreakFrame((u4*)caller) && 93530bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee SAVEAREA_FROM_FP(caller)->prevFrame == NULL) 936f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return NULL; 937f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 938f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* go one more */ 939f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project callerCaller = dvmGetCallerFP(caller); 940f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (callerCaller == NULL) 941f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return NULL; 942f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 943f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return SAVEAREA_FROM_FP(callerCaller)->method->clazz; 944f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 945f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 946f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 947f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get the caller's caller's caller's class. Pass in the current fp. 948f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 949f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This is used by e.g. java.lang.Class, which wants to know about the 950f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * class loader of the method that called it. 951f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 952f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectClassObject* dvmGetCaller3Class(const void* curFrame) 953f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 954f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project void* caller = SAVEAREA_FROM_FP(curFrame)->prevFrame; 955f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int i; 956f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 957f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* at the top? */ 95830bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee if (dvmIsBreakFrame((u4*)caller) && 95930bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee SAVEAREA_FROM_FP(caller)->prevFrame == NULL) 960f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return NULL; 961f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 962f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Walk up two frames if possible. */ 963f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (i = 0; i < 2; i++) { 964f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project caller = dvmGetCallerFP(caller); 965f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (caller == NULL) 966f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return NULL; 967f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 968de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro 969f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return SAVEAREA_FROM_FP(caller)->method->clazz; 970f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 971f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 972f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 973db0c9549818d9f6e508d26e45ff9d886802aa1daCarl Shapiro * Fill a flat array of methods that comprise the current interpreter 974db0c9549818d9f6e508d26e45ff9d886802aa1daCarl Shapiro * stack trace. Pass in the current frame ptr. Break frames are 975db0c9549818d9f6e508d26e45ff9d886802aa1daCarl Shapiro * skipped, but reflection invocations are not. 976f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 977f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The current frame will be in element 0. 978f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 979db0c9549818d9f6e508d26e45ff9d886802aa1daCarl Shapirovoid dvmFillStackTraceArray(const void* fp, const Method** array, size_t length) 980f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 981db0c9549818d9f6e508d26e45ff9d886802aa1daCarl Shapiro assert(fp != NULL); 982db0c9549818d9f6e508d26e45ff9d886802aa1daCarl Shapiro assert(array != NULL); 983db0c9549818d9f6e508d26e45ff9d886802aa1daCarl Shapiro size_t i = 0; 984db0c9549818d9f6e508d26e45ff9d886802aa1daCarl Shapiro while (fp != NULL) { 985db0c9549818d9f6e508d26e45ff9d886802aa1daCarl Shapiro if (!dvmIsBreakFrame((u4*)fp)) { 986db0c9549818d9f6e508d26e45ff9d886802aa1daCarl Shapiro assert(i < length); 987db0c9549818d9f6e508d26e45ff9d886802aa1daCarl Shapiro array[i++] = SAVEAREA_FROM_FP(fp)->method; 988db0c9549818d9f6e508d26e45ff9d886802aa1daCarl Shapiro } 989db0c9549818d9f6e508d26e45ff9d886802aa1daCarl Shapiro fp = SAVEAREA_FROM_FP(fp)->prevFrame; 990f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 991f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 992f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 993f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 994f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Open up the reserved area and throw an exception. The reserved area 995f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * should only be needed to create and initialize the exception itself. 996f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 997f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If we already opened it and we're continuing to overflow, abort the VM. 998f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 999f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We have to leave the "reserved" area open until the "catch" handler has 1000f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * finished doing its processing. This is because the catch handler may 1001f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * need to resolve classes, which requires calling into the class loader if 1002f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the classes aren't already in the "initiating loader" list. 1003f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 10046ed1a0f396a1857c31b486d3e93ee2dbeb49a6cdAndy McFaddenvoid dvmHandleStackOverflow(Thread* self, const Method* method) 1005f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 1006f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 1007f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Can we make the reserved area available? 1008f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1009f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (self->stackOverflowed) { 1010f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 1011f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Already did, nothing to do but bail. 1012f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 101360fc806b679a3655c228b4093058c59941a49cfeDan Bornstein LOGE("DalvikVM: double-overflow of stack in threadid=%d; aborting", 1014f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->threadId); 1015f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmDumpThread(self, false); 1016f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmAbort(); 1017f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1018f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1019f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* open it up to the full range */ 102060fc806b679a3655c228b4093058c59941a49cfeDan Bornstein LOGI("threadid=%d: stack overflow on call to %s.%s:%s", 10216ed1a0f396a1857c31b486d3e93ee2dbeb49a6cdAndy McFadden self->threadId, 10226ed1a0f396a1857c31b486d3e93ee2dbeb49a6cdAndy McFadden method->clazz->descriptor, method->name, method->shorty); 102330bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee StackSaveArea* saveArea = SAVEAREA_FROM_FP(self->interpSave.curFrame); 102460fc806b679a3655c228b4093058c59941a49cfeDan Bornstein LOGI(" method requires %d+%d+%d=%d bytes, fp is %p (%d left)", 10256ed1a0f396a1857c31b486d3e93ee2dbeb49a6cdAndy McFadden method->registersSize * 4, sizeof(StackSaveArea), method->outsSize * 4, 10266ed1a0f396a1857c31b486d3e93ee2dbeb49a6cdAndy McFadden (method->registersSize + method->outsSize) * 4 + sizeof(StackSaveArea), 10276ed1a0f396a1857c31b486d3e93ee2dbeb49a6cdAndy McFadden saveArea, (u1*) saveArea - self->interpStackEnd); 102860fc806b679a3655c228b4093058c59941a49cfeDan Bornstein LOGI(" expanding stack end (%p to %p)", self->interpStackEnd, 1029f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->interpStackStart - self->interpStackSize); 1030f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project //dvmDumpThread(self, false); 1031f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->interpStackEnd = self->interpStackStart - self->interpStackSize; 1032f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->stackOverflowed = true; 1033f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1034f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 1035f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If we were trying to throw an exception when the stack overflowed, 1036f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * we will blow up when doing the class lookup on StackOverflowError 1037f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * because of the pending exception. So, we clear it and make it 1038f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the cause of the SOE. 1039f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1040f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Object* excep = dvmGetException(self); 1041f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (excep != NULL) { 104260fc806b679a3655c228b4093058c59941a49cfeDan Bornstein LOGW("Stack overflow while throwing exception"); 1043f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmClearException(self); 1044f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 10450b8b293f228b3d341054bc1fad8a92d6e533b4ddDan Bornstein dvmThrowChainedException(gDvm.exStackOverflowError, NULL, excep); 1046f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1047f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1048f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 1049f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Reduce the available stack size. By this point we should have finished 1050f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * our overflow processing. 1051f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 10524fbba1f95b3e27bdc5f5572bb0420b5f928aa54eAndy McFaddenvoid dvmCleanupStackOverflow(Thread* self, const Object* exception) 1053f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 1054f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const u1* newStackEnd; 1055f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1056f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(self->stackOverflowed); 1057f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 105832bb3da6f05959749161ce7f9103027f11597fe3Dan Bornstein if (exception->clazz != gDvm.exStackOverflowError) { 10594fbba1f95b3e27bdc5f5572bb0420b5f928aa54eAndy McFadden /* exception caused during SOE, not the SOE itself */ 10604fbba1f95b3e27bdc5f5572bb0420b5f928aa54eAndy McFadden return; 10614fbba1f95b3e27bdc5f5572bb0420b5f928aa54eAndy McFadden } 10624fbba1f95b3e27bdc5f5572bb0420b5f928aa54eAndy McFadden 1063f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project newStackEnd = (self->interpStackStart - self->interpStackSize) 1064f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project + STACK_OVERFLOW_RESERVE; 106530bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee if ((u1*)self->interpSave.curFrame <= newStackEnd) { 106660fc806b679a3655c228b4093058c59941a49cfeDan Bornstein LOGE("Can't shrink stack: curFrame is in reserved area (%p %p)", 106730bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee self->interpStackEnd, self->interpSave.curFrame); 1068f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmDumpThread(self, false); 1069f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmAbort(); 1070f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1071f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1072f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->interpStackEnd = newStackEnd; 1073f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->stackOverflowed = false; 1074f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 107560fc806b679a3655c228b4093058c59941a49cfeDan Bornstein LOGI("Shrank stack (to %p, curFrame is %p)", self->interpStackEnd, 107630bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee self->interpSave.curFrame); 1077f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1078f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1079f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1080f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 1081fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * Extract the object that is the target of a monitor-enter instruction 1082fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * in the top stack frame of "thread". 1083fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * 1084fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * The other thread might be alive, so this has to work carefully. 1085fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * 1086d19988d14f24086ea1bb37cf662c8729ff78e113Andy McFadden * The thread list lock must be held. 1087fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * 1088fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * Returns "true" if we successfully recover the object. "*pOwner" will 1089fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * be NULL if we can't determine the owner for some reason (e.g. race 1090fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * condition on ownership transfer). 1091fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden */ 1092fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFaddenstatic bool extractMonitorEnterObject(Thread* thread, Object** pLockObj, 1093fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden Thread** pOwner) 1094fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden{ 109530bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee void* framePtr = thread->interpSave.curFrame; 1096fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden 1097fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro if (framePtr == NULL || dvmIsBreakFrame((u4*)framePtr)) 1098fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden return false; 1099fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden 1100fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden const StackSaveArea* saveArea = SAVEAREA_FROM_FP(framePtr); 1101fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden const Method* method = saveArea->method; 1102fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden const u2* currentPc = saveArea->xtra.currentPc; 1103fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden 1104fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden /* check Method* */ 1105fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden if (!dvmLinearAllocContains(method, sizeof(Method))) { 110660fc806b679a3655c228b4093058c59941a49cfeDan Bornstein LOGD("ExtrMon: method %p not valid", method); 1107fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden return false; 1108fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden } 1109fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden 1110fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden /* check currentPc */ 1111fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden u4 insnsSize = dvmGetMethodInsnsSize(method); 1112fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden if (currentPc < method->insns || 1113fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden currentPc >= method->insns + insnsSize) 1114fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden { 111560fc806b679a3655c228b4093058c59941a49cfeDan Bornstein LOGD("ExtrMon: insns %p not valid (%p - %p)", 1116fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden currentPc, method->insns, method->insns + insnsSize); 1117fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden return false; 1118fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden } 1119fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden 1120fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden /* check the instruction */ 1121fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden if ((*currentPc & 0xff) != OP_MONITOR_ENTER) { 112260fc806b679a3655c228b4093058c59941a49cfeDan Bornstein LOGD("ExtrMon: insn at %p is not monitor-enter (0x%02x)", 1123fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden currentPc, *currentPc & 0xff); 1124fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden return false; 1125fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden } 1126fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden 1127fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden /* get and check the register index */ 1128fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden unsigned int reg = *currentPc >> 8; 1129fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden if (reg >= method->registersSize) { 113060fc806b679a3655c228b4093058c59941a49cfeDan Bornstein LOGD("ExtrMon: invalid register %d (max %d)", 1131fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden reg, method->registersSize); 1132fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden return false; 1133fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden } 1134fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden 1135fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden /* get and check the object in that register */ 1136fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden u4* fp = (u4*) framePtr; 1137fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden Object* obj = (Object*) fp[reg]; 11388bc8bf71a52e17d483021b4c9dc8e735d9bce3edElliott Hughes if (obj != NULL && !dvmIsHeapAddress(obj)) { 113960fc806b679a3655c228b4093058c59941a49cfeDan Bornstein LOGD("ExtrMon: invalid object %p at %p[%d]", obj, fp, reg); 1140fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden return false; 1141fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden } 1142fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden *pLockObj = obj; 1143fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden 1144fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden /* 1145fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * Try to determine the object's lock holder; it's okay if this fails. 1146fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * 1147fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * We're assuming the thread list lock is already held by this thread. 1148fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * If it's not, we may be living dangerously if we have to scan through 1149fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * the thread list to find a match. (The VM will generally be in a 1150fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * suspended state when executing here, so this is a minor concern 1151fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * unless we're dumping while threads are running, in which case there's 1152fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * a good chance of stuff blowing up anyway.) 1153fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden */ 1154fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden *pOwner = dvmGetObjectLockHolder(obj); 1155fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden 1156fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden return true; 1157fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden} 1158fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden 1159708f143f318bb2167c810f9506102f4ad656545cElliott Hughesstatic void printWaitMessage(const DebugOutputTarget* target, const char* detail, Object* obj, 1160708f143f318bb2167c810f9506102f4ad656545cElliott Hughes Thread* thread) 1161708f143f318bb2167c810f9506102f4ad656545cElliott Hughes{ 1162837eabb829417c1542037423c55536649de404b8Elliott Hughes std::string msg(StringPrintf(" - waiting %s <%p> ", detail, obj)); 1163708f143f318bb2167c810f9506102f4ad656545cElliott Hughes 1164708f143f318bb2167c810f9506102f4ad656545cElliott Hughes if (obj->clazz != gDvm.classJavaLangClass) { 1165708f143f318bb2167c810f9506102f4ad656545cElliott Hughes // I(16573) - waiting on <0xf5feda38> (a java.util.LinkedList) 1166fe7f2b3920bf5d66eda262e643245b03df3e57c8Elliott Hughes // I(16573) - waiting on <0xf5ed54f8> (a java.lang.Class<java.lang.ref.ReferenceQueue>) 1167fe7f2b3920bf5d66eda262e643245b03df3e57c8Elliott Hughes msg += "(a " + dvmHumanReadableType(obj) + ")"; 1168708f143f318bb2167c810f9506102f4ad656545cElliott Hughes } 1169708f143f318bb2167c810f9506102f4ad656545cElliott Hughes 1170708f143f318bb2167c810f9506102f4ad656545cElliott Hughes if (thread != NULL) { 1171708f143f318bb2167c810f9506102f4ad656545cElliott Hughes std::string threadName(dvmGetThreadName(thread)); 1172837eabb829417c1542037423c55536649de404b8Elliott Hughes StringAppendF(&msg, " held by tid=%d (%s)", thread->threadId, threadName.c_str()); 1173708f143f318bb2167c810f9506102f4ad656545cElliott Hughes } 1174708f143f318bb2167c810f9506102f4ad656545cElliott Hughes 1175708f143f318bb2167c810f9506102f4ad656545cElliott Hughes dvmPrintDebugMessage(target, "%s\n", msg.c_str()); 1176708f143f318bb2167c810f9506102f4ad656545cElliott Hughes} 1177708f143f318bb2167c810f9506102f4ad656545cElliott Hughes 1178fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden/* 1179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Dump stack frames, starting from the specified frame and moving down. 1180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 1181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Each frame holds a pointer to the currently executing method, and the 1182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * saved program counter from the caller ("previous" frame). This means 1183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * we don't have the PC for the current method on the stack, which is 1184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * pretty reasonable since it's in the "PC register" for the VM. Because 1185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * exceptions need to show the correct line number we actually *do* have 1186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * an updated version in the fame's "xtra.currentPc", but it's unreliable. 1187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 1188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Note "framePtr" could be NULL in rare circumstances. 1189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void dumpFrames(const DebugOutputTarget* target, void* framePtr, 1191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Thread* thread) 1192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 1193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const StackSaveArea* saveArea; 1194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const Method* method; 1195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int checkCount = 0; 1196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const u2* currentPc = NULL; 1197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project bool first = true; 1198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 1200d19988d14f24086ea1bb37cf662c8729ff78e113Andy McFadden * We call functions that require us to be holding the thread list lock. 1201d19988d14f24086ea1bb37cf662c8729ff78e113Andy McFadden * It's probable that the caller has already done so, but it's not 1202d19988d14f24086ea1bb37cf662c8729ff78e113Andy McFadden * guaranteed. If it's not locked, lock it now. 1203d19988d14f24086ea1bb37cf662c8729ff78e113Andy McFadden */ 1204d19988d14f24086ea1bb37cf662c8729ff78e113Andy McFadden bool needThreadUnlock = dvmTryLockThreadList(); 1205d19988d14f24086ea1bb37cf662c8729ff78e113Andy McFadden 1206d19988d14f24086ea1bb37cf662c8729ff78e113Andy McFadden /* 1207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The "currentPc" is updated whenever we execute an instruction that 1208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * might throw an exception. Show it here. 1209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1210fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro if (framePtr != NULL && !dvmIsBreakFrame((u4*)framePtr)) { 1211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveArea = SAVEAREA_FROM_FP(framePtr); 1212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (saveArea->xtra.currentPc != NULL) 1214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project currentPc = saveArea->xtra.currentPc; 1215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project while (framePtr != NULL) { 1218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveArea = SAVEAREA_FROM_FP(framePtr); 1219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project method = saveArea->method; 1220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1221fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro if (dvmIsBreakFrame((u4*)framePtr)) { 1222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project //dvmPrintDebugMessage(target, " (break frame)\n"); 1223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 1224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int relPc; 1225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (currentPc != NULL) 1227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project relPc = currentPc - saveArea->method->insns; 1228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project else 1229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project relPc = -1; 1230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 12315719d5c79558ffdbbb863ddcf61836221aba922dElliott Hughes std::string methodName(dvmHumanReadableMethod(method, false)); 1232b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes if (dvmIsNativeMethod(method)) { 12335719d5c79558ffdbbb863ddcf61836221aba922dElliott Hughes dvmPrintDebugMessage(target, " at %s(Native Method)\n", 12345719d5c79558ffdbbb863ddcf61836221aba922dElliott Hughes methodName.c_str()); 1235b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes } else { 12365719d5c79558ffdbbb863ddcf61836221aba922dElliott Hughes dvmPrintDebugMessage(target, " at %s(%s:%s%d)\n", 12375719d5c79558ffdbbb863ddcf61836221aba922dElliott Hughes methodName.c_str(), dvmGetMethodSourceFile(method), 1238b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes (relPc >= 0 && first) ? "~" : "", 1239b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes relPc < 0 ? -1 : dvmLineNumFromPC(method, relPc)); 1240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1242fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden if (first) { 1243fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden /* 1244fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * Decorate WAIT and MONITOR threads with some detail on 1245fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * the first frame. 1246fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * 1247fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * warning: wait status not stable, even in suspend 1248fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden */ 1249fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden if (thread->status == THREAD_WAIT || 1250fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden thread->status == THREAD_TIMED_WAIT) 1251fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden { 1252fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden Monitor* mon = thread->waitMonitor; 1253fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden Object* obj = dvmGetMonitorObject(mon); 1254fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden if (obj != NULL) { 1255d19988d14f24086ea1bb37cf662c8729ff78e113Andy McFadden Thread* joinThread = NULL; 1256708f143f318bb2167c810f9506102f4ad656545cElliott Hughes if (obj->clazz == gDvm.classJavaLangVMThread) { 1257d19988d14f24086ea1bb37cf662c8729ff78e113Andy McFadden joinThread = dvmGetThreadFromThreadObject(obj); 1258d19988d14f24086ea1bb37cf662c8729ff78e113Andy McFadden } 1259708f143f318bb2167c810f9506102f4ad656545cElliott Hughes printWaitMessage(target, "on", obj, joinThread); 1260fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden } 1261fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden } else if (thread->status == THREAD_MONITOR) { 1262fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden Object* obj; 1263fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden Thread* owner; 1264fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden if (extractMonitorEnterObject(thread, &obj, &owner)) { 1265708f143f318bb2167c810f9506102f4ad656545cElliott Hughes printWaitMessage(target, "to lock", obj, owner); 1266fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden } 1267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 1272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get saved PC for previous frame. There's no savedPc in a "break" 1273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * frame, because that represents native or interpreted code 1274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * invoked by the VM. The saved PC is sitting in the "PC register", 1275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * a local variable on the native stack. 1276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project currentPc = saveArea->savedPc; 1278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project first = false; 1280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 12810083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden if (saveArea->prevFrame != NULL && saveArea->prevFrame <= framePtr) { 128260fc806b679a3655c228b4093058c59941a49cfeDan Bornstein LOGW("Warning: loop in stack trace at frame %d (%p -> %p)", 12830083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden checkCount, framePtr, saveArea->prevFrame); 12840083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden break; 12850083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden } 1286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project framePtr = saveArea->prevFrame; 1287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project checkCount++; 12890083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden if (checkCount > 300) { 1290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmPrintDebugMessage(target, 1291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project " ***** printed %d frames, not showing any more\n", 1292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project checkCount); 1293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 1294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmPrintDebugMessage(target, "\n"); 1297d19988d14f24086ea1bb37cf662c8729ff78e113Andy McFadden 1298d19988d14f24086ea1bb37cf662c8729ff78e113Andy McFadden if (needThreadUnlock) { 1299d19988d14f24086ea1bb37cf662c8729ff78e113Andy McFadden dvmUnlockThreadList(); 1300d19988d14f24086ea1bb37cf662c8729ff78e113Andy McFadden } 1301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 1305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Dump the stack for the specified thread. 1306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmDumpThreadStack(const DebugOutputTarget* target, Thread* thread) 1308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 130930bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee dumpFrames(target, thread->interpSave.curFrame, thread); 1310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 1313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Dump the stack for the specified thread, which is still running. 1314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 1315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This is very dangerous, because stack frames are being pushed on and 1316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * popped off, and if the thread exits we'll be looking at freed memory. 1317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The plan here is to take a snapshot of the stack and then dump that 1318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * to try to minimize the chances of catching it mid-update. This should 1319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * work reasonably well on a single-CPU system. 1320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 1321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * There is a small chance that calling here will crash the VM. 1322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmDumpRunningThreadStack(const DebugOutputTarget* target, Thread* thread) 1324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 1325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project StackSaveArea* saveArea; 1326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const u1* origStack; 1327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project u1* stackCopy = NULL; 1328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int origSize, fpOffset; 1329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project void* fp; 1330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int depthLimit = 200; 1331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 133230bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee if (thread == NULL || thread->interpSave.curFrame == NULL) { 1333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmPrintDebugMessage(target, 1334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "DumpRunning: Thread at %p has no curFrame (threadid=%d)\n", 1335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project thread, (thread != NULL) ? thread->threadId : 0); 1336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return; 1337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* wait for a full quantum */ 1340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project sched_yield(); 1341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* copy the info we need, then the stack itself */ 1343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project origSize = thread->interpStackSize; 1344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project origStack = (const u1*) thread->interpStackStart - origSize; 1345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stackCopy = (u1*) malloc(origSize); 134630bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee fpOffset = (u1*) thread->interpSave.curFrame - origStack; 1347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project memcpy(stackCopy, origStack, origSize); 1348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 1350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Run through the stack and rewrite the "prev" pointers. 1351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 135260fc806b679a3655c228b4093058c59941a49cfeDan Bornstein //LOGI("DR: fpOff=%d (from %p %p)",fpOffset, origStack, 135330bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee // thread->interpSave.curFrame); 1354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project fp = stackCopy + fpOffset; 1355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project while (true) { 1356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int prevOffset; 1357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (depthLimit-- < 0) { 1359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* we're probably screwed */ 1360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmPrintDebugMessage(target, "DumpRunning: depth limit hit\n"); 1361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmAbort(); 1362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveArea = SAVEAREA_FROM_FP(fp); 1364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (saveArea->prevFrame == NULL) 1365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 1366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project prevOffset = (u1*) saveArea->prevFrame - origStack; 1368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (prevOffset < 0 || prevOffset > origSize) { 1369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmPrintDebugMessage(target, 1370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "DumpRunning: bad offset found: %d (from %p %p)\n", 1371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project prevOffset, origStack, saveArea->prevFrame); 1372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveArea->prevFrame = NULL; 1373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 1374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 137630bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee saveArea->prevFrame = (u4*)(stackCopy + prevOffset); 1377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project fp = saveArea->prevFrame; 1378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 1381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We still need to pass the Thread for some monitor wait stuff. 1382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dumpFrames(target, stackCopy + fpOffset, thread); 1384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project free(stackCopy); 1385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1386