Stack.cpp revision 6f3c21fb026d9489e5046416bcd5a84fa8e4615b
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 459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(obj != NULL && dvmIsValidObject(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*); 484f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(obj == NULL || dvmIsValidObject(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 636be88d8aa9753657566cca479609b4f79d095ad42Elliott Hughesstatic void throwArgumentTypeMismatch(int argIndex, ClassObject* expected, 637be88d8aa9753657566cca479609b4f79d095ad42Elliott Hughes DataObject* arg) 638be88d8aa9753657566cca479609b4f79d095ad42Elliott Hughes{ 639be88d8aa9753657566cca479609b4f79d095ad42Elliott Hughes char* expectedClassName = dvmHumanReadableDescriptor(expected->descriptor); 640be88d8aa9753657566cca479609b4f79d095ad42Elliott Hughes char* actualClassName = (arg != NULL) 6417cc095f8e3ec52ba94d91e1d327354f61236496aCarl Shapiro ? dvmHumanReadableDescriptor(arg->clazz->descriptor) 642be88d8aa9753657566cca479609b4f79d095ad42Elliott Hughes : strdup("null"); 6430b8b293f228b3d341054bc1fad8a92d6e533b4ddDan Bornstein dvmThrowExceptionFmt(gDvm.exIllegalArgumentException, 644be88d8aa9753657566cca479609b4f79d095ad42Elliott Hughes "argument %d should have type %s, got %s", 645be88d8aa9753657566cca479609b4f79d095ad42Elliott Hughes argIndex + 1, expectedClassName, actualClassName); 646be88d8aa9753657566cca479609b4f79d095ad42Elliott Hughes free(expectedClassName); 647be88d8aa9753657566cca479609b4f79d095ad42Elliott Hughes free(actualClassName); 648be88d8aa9753657566cca479609b4f79d095ad42Elliott Hughes} 649be88d8aa9753657566cca479609b4f79d095ad42Elliott Hughes 650f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 651f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Invoke a method, using the specified arguments and return type, through 652f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * one of the reflection interfaces. Could be a virtual or direct method 653f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (including constructors). Used for reflection. 654f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 655f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Deals with boxing/unboxing primitives and performs widening conversions. 656f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 657f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "invokeObj" will be null for a static method. 658f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 659f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If the invocation returns with an exception raised, we have to wrap it. 660f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 661f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectObject* dvmInvokeMethod(Object* obj, const Method* method, 662f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ArrayObject* argList, ArrayObject* params, ClassObject* returnType, 663f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project bool noAccessCheck) 664f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 665f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ClassObject* clazz; 666f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Object* retObj = NULL; 667f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Thread* self = dvmThreadSelf(); 668f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project s4* ins; 669f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int verifyCount, argListLength; 670f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project JValue retval; 671be420e7ce02692164617fab07facb514147abaa8Andy McFadden bool needPop = false; 672f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 673f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* verify arg count */ 674f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (argList != NULL) 675f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project argListLength = argList->length; 676f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project else 677f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project argListLength = 0; 678f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (argListLength != (int) params->length) { 6790b8b293f228b3d341054bc1fad8a92d6e533b4ddDan Bornstein dvmThrowExceptionFmt(gDvm.exIllegalArgumentException, 680be88d8aa9753657566cca479609b4f79d095ad42Elliott Hughes "wrong number of arguments; expected %d, got %d", 681f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project params->length, argListLength); 682f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return NULL; 683f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 684f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 685f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project clazz = callPrep(self, method, obj, !noAccessCheck); 686f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (clazz == NULL) 687f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return NULL; 688be420e7ce02692164617fab07facb514147abaa8Andy McFadden needPop = true; 689f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 690f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* "ins" for new frame start at frame pointer plus locals */ 69130bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee ins = ((s4*)self->interpSave.curFrame) + 69230bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee (method->registersSize - method->insSize); 693f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project verifyCount = 0; 694f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 69560fc806b679a3655c228b4093058c59941a49cfeDan Bornstein //LOGD(" FP is %p, INs live at >= %p", self->interpSave.curFrame, ins); 696f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 697f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* put "this" pointer into in0 if appropriate */ 698f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!dvmIsStaticMethod(method)) { 699f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(obj != NULL); 700f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *ins++ = (s4) obj; 701f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project verifyCount++; 702f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 703f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 704f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 705f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Copy the args onto the stack. Primitive types are converted when 706f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * necessary, and object types are verified. 707f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 7081813ab265f691e93401c7307c0b34247842ab35eCarl Shapiro DataObject** args = (DataObject**)(void*)argList->contents; 7091813ab265f691e93401c7307c0b34247842ab35eCarl Shapiro ClassObject** types = (ClassObject**)(void*)params->contents; 7101813ab265f691e93401c7307c0b34247842ab35eCarl Shapiro for (int i = 0; i < argListLength; i++) { 7111813ab265f691e93401c7307c0b34247842ab35eCarl Shapiro int width = dvmConvertArgument(*args++, *types++, ins); 712f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (width < 0) { 713f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmPopFrame(self); // throw wants to pull PC out of stack 714be420e7ce02692164617fab07facb514147abaa8Andy McFadden needPop = false; 715be88d8aa9753657566cca479609b4f79d095ad42Elliott Hughes throwArgumentTypeMismatch(i, *(types-1), *(args-1)); 716be420e7ce02692164617fab07facb514147abaa8Andy McFadden goto bail; 717f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 718f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 719f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ins += width; 720f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project verifyCount += width; 721f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 722f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 723c4ae06fe78cffa815225f9bcd26c19e6714db572Andy McFadden#ifndef NDEBUG 724f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (verifyCount != method->insSize) { 72560fc806b679a3655c228b4093058c59941a49cfeDan Bornstein LOGE("Got vfycount=%d insSize=%d for %s.%s", verifyCount, 726f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project method->insSize, clazz->descriptor, method->name); 727f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(false); 728f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 729f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 730c4ae06fe78cffa815225f9bcd26c19e6714db572Andy McFadden#endif 731f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 732f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (dvmIsNativeMethod(method)) { 73399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project TRACE_METHOD_ENTER(self, method); 734f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 735f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Because we leave no space for local variables, "curFrame" points 736f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * directly at the method arguments. 737f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 73830bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee (*method->nativeFunc)((u4*)self->interpSave.curFrame, &retval, 73930bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee method, self); 74099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project TRACE_METHOD_EXIT(self, method); 741f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 742f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmInterpret(self, method, &retval); 743f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 744f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 745f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 746be420e7ce02692164617fab07facb514147abaa8Andy McFadden * Pop the frame immediately. The "wrap" calls below can cause 747be420e7ce02692164617fab07facb514147abaa8Andy McFadden * allocations, and we don't want the GC to walk the now-dead frame. 748be420e7ce02692164617fab07facb514147abaa8Andy McFadden */ 749be420e7ce02692164617fab07facb514147abaa8Andy McFadden dvmPopFrame(self); 750be420e7ce02692164617fab07facb514147abaa8Andy McFadden needPop = false; 751be420e7ce02692164617fab07facb514147abaa8Andy McFadden 752be420e7ce02692164617fab07facb514147abaa8Andy McFadden /* 753f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If an exception is raised, wrap and replace. This is necessary 754f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * because the invoked method could have thrown a checked exception 755f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * that the caller wasn't prepared for. 756f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 757f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We might be able to do this up in the interpreted code, but that will 758f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * leave us with a shortened stack trace in the top-level exception. 759f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 760f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (dvmCheckException(self)) { 761f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmWrapException("Ljava/lang/reflect/InvocationTargetException;"); 762f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 763f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 764f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If this isn't a void method or constructor, convert the return type 765f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * to an appropriate object. 766f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 767f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We don't do this when an exception is raised because the value 768f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * in "retval" is undefined. 769f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 770f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (returnType != NULL) { 771c4ae06fe78cffa815225f9bcd26c19e6714db572Andy McFadden retObj = (Object*)dvmBoxPrimitive(retval, returnType); 772f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmReleaseTrackedAlloc(retObj, NULL); 773f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 774f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 775f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 776f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail: 777be420e7ce02692164617fab07facb514147abaa8Andy McFadden if (needPop) { 778be420e7ce02692164617fab07facb514147abaa8Andy McFadden dvmPopFrame(self); 779be420e7ce02692164617fab07facb514147abaa8Andy McFadden } 780f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return retObj; 781f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 782f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 783d862faa2ceae186da5518607505eb942d634ced9Carl Shapirostruct LineNumFromPcContext { 784f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project u4 address; 785f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project u4 lineNum; 786d862faa2ceae186da5518607505eb942d634ced9Carl Shapiro}; 787f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 788f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic int lineNumForPcCb(void *cnxt, u4 address, u4 lineNum) 789f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 790f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LineNumFromPcContext *pContext = (LineNumFromPcContext *)cnxt; 791f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 792de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro // We know that this callback will be called in 793f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // ascending address order, so keep going until we find 794f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // a match or we've just gone past it. 795f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 796f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (address > pContext->address) { 797f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // The line number from the previous positions callback 798f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // wil be the final result. 799f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return 1; 800f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 801f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 802f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pContext->lineNum = lineNum; 803f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 804f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return (address == pContext->address) ? 1 : 0; 805f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 806f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 807f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 808f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Determine the source file line number based on the program counter. 809f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "pc" is an offset, in 16-bit units, from the start of the method's code. 810f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 811f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns -1 if no match was found (possibly because the source files were 812f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * compiled without "-g", so no line number information is present). 813f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns -2 for native methods (as expected in exception traces). 814f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 815f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint dvmLineNumFromPC(const Method* method, u4 relPc) 816f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 817f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const DexCode* pDexCode = dvmGetMethodCode(method); 818f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 819f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (pDexCode == NULL) { 820f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (dvmIsNativeMethod(method) && !dvmIsAbstractMethod(method)) 821f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return -2; 822f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return -1; /* can happen for abstract method stub */ 823f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 824f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 825f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LineNumFromPcContext context; 826f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project memset(&context, 0, sizeof(context)); 827f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project context.address = relPc; 828f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // A method with no line number info should return -1 829f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project context.lineNum = -1; 830f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 831f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dexDecodeDebugInfo(method->clazz->pDvmDex->pDexFile, pDexCode, 832f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project method->clazz->descriptor, 833f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project method->prototype.protoIdx, 834f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project method->accessFlags, 835f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project lineNumForPcCb, NULL, &context); 836de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro 837f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return context.lineNum; 838f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 839f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 840f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 841f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Compute the frame depth. 842f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 843f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Excludes "break" frames. 844f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 845f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint dvmComputeExactFrameDepth(const void* fp) 846f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 847f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int count = 0; 848f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 849f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for ( ; fp != NULL; fp = SAVEAREA_FROM_FP(fp)->prevFrame) { 850fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro if (!dvmIsBreakFrame((u4*)fp)) 851f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project count++; 852f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 853f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 854f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return count; 855f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 856f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 857f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 858f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Compute the "vague" frame depth, which is just a pointer subtraction. 859f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The result is NOT an overly generous assessment of the number of 860f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * frames; the only meaningful use is to compare against the result of 861f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * an earlier invocation. 862f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 863f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Useful for implementing single-step debugger modes, which may need to 864f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * call this for every instruction. 865f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 866f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint dvmComputeVagueFrameDepth(Thread* thread, const void* fp) 867f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 868f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const u1* interpStackStart = thread->interpStackStart; 869f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 870e3c01dac83e6eea7f82fe81ed89cfbdd9791dbc9Carl Shapiro assert((u1*) fp >= interpStackStart - thread->interpStackSize); 871e3c01dac83e6eea7f82fe81ed89cfbdd9791dbc9Carl Shapiro assert((u1*) fp < interpStackStart); 872f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return interpStackStart - (u1*) fp; 873f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 874f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 875f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 876f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get the calling frame. Pass in the current fp. 877f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 878f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Skip "break" frames and reflection invoke frames. 879f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 880f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid* dvmGetCallerFP(const void* curFrame) 881f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 882f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project void* caller = SAVEAREA_FROM_FP(curFrame)->prevFrame; 883f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project StackSaveArea* saveArea; 884f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 885f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectretry: 886fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro if (dvmIsBreakFrame((u4*)caller)) { 887f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* pop up one more */ 888f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project caller = SAVEAREA_FROM_FP(caller)->prevFrame; 889f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (caller == NULL) 890f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return NULL; /* hit the top */ 891f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 892f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 893f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If we got here by java.lang.reflect.Method.invoke(), we don't 894f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * want to return Method's class loader. Shift up one and try 895f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * again. 896f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 897f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveArea = SAVEAREA_FROM_FP(caller); 898f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (dvmIsReflectionMethod(saveArea->method)) { 899f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project caller = saveArea->prevFrame; 900f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(caller != NULL); 901f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto retry; 902f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 903f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 904f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 905f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return caller; 906f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 907f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 908f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 909f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get the caller's class. Pass in the current fp. 910f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 911f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This is used by e.g. java.lang.Class. 912f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 913f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectClassObject* dvmGetCallerClass(const void* curFrame) 914f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 915f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project void* caller; 916f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 917f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project caller = dvmGetCallerFP(curFrame); 918f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (caller == NULL) 919f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return NULL; 920f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 921f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return SAVEAREA_FROM_FP(caller)->method->clazz; 922f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 923f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 924f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 925f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get the caller's caller's class. Pass in the current fp. 926f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 927f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This is used by e.g. java.lang.Class, which wants to know about the 928f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * class loader of the method that called it. 929f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 930f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectClassObject* dvmGetCaller2Class(const void* curFrame) 931f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 932f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project void* caller = SAVEAREA_FROM_FP(curFrame)->prevFrame; 933f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project void* callerCaller; 934f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 935f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* at the top? */ 93630bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee if (dvmIsBreakFrame((u4*)caller) && 93730bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee SAVEAREA_FROM_FP(caller)->prevFrame == NULL) 938f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return NULL; 939f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 940f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* go one more */ 941f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project callerCaller = dvmGetCallerFP(caller); 942f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (callerCaller == NULL) 943f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return NULL; 944f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 945f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return SAVEAREA_FROM_FP(callerCaller)->method->clazz; 946f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 947f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 948f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 949f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get the caller's caller's caller's class. Pass in the current fp. 950f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 951f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This is used by e.g. java.lang.Class, which wants to know about the 952f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * class loader of the method that called it. 953f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 954f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectClassObject* dvmGetCaller3Class(const void* curFrame) 955f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 956f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project void* caller = SAVEAREA_FROM_FP(curFrame)->prevFrame; 957f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int i; 958f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 959f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* at the top? */ 96030bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee if (dvmIsBreakFrame((u4*)caller) && 96130bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee SAVEAREA_FROM_FP(caller)->prevFrame == NULL) 962f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return NULL; 963f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 964f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Walk up two frames if possible. */ 965f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (i = 0; i < 2; i++) { 966f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project caller = dvmGetCallerFP(caller); 967f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (caller == NULL) 968f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return NULL; 969f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 970de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro 971f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return SAVEAREA_FROM_FP(caller)->method->clazz; 972f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 973f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 974f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 975db0c9549818d9f6e508d26e45ff9d886802aa1daCarl Shapiro * Fill a flat array of methods that comprise the current interpreter 976db0c9549818d9f6e508d26e45ff9d886802aa1daCarl Shapiro * stack trace. Pass in the current frame ptr. Break frames are 977db0c9549818d9f6e508d26e45ff9d886802aa1daCarl Shapiro * skipped, but reflection invocations are not. 978f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 979f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The current frame will be in element 0. 980f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 981db0c9549818d9f6e508d26e45ff9d886802aa1daCarl Shapirovoid dvmFillStackTraceArray(const void* fp, const Method** array, size_t length) 982f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 983db0c9549818d9f6e508d26e45ff9d886802aa1daCarl Shapiro assert(fp != NULL); 984db0c9549818d9f6e508d26e45ff9d886802aa1daCarl Shapiro assert(array != NULL); 985db0c9549818d9f6e508d26e45ff9d886802aa1daCarl Shapiro size_t i = 0; 986db0c9549818d9f6e508d26e45ff9d886802aa1daCarl Shapiro while (fp != NULL) { 987db0c9549818d9f6e508d26e45ff9d886802aa1daCarl Shapiro if (!dvmIsBreakFrame((u4*)fp)) { 988db0c9549818d9f6e508d26e45ff9d886802aa1daCarl Shapiro assert(i < length); 989db0c9549818d9f6e508d26e45ff9d886802aa1daCarl Shapiro array[i++] = SAVEAREA_FROM_FP(fp)->method; 990db0c9549818d9f6e508d26e45ff9d886802aa1daCarl Shapiro } 991db0c9549818d9f6e508d26e45ff9d886802aa1daCarl Shapiro fp = SAVEAREA_FROM_FP(fp)->prevFrame; 992f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 993f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 994f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 995f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 996f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Open up the reserved area and throw an exception. The reserved area 997f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * should only be needed to create and initialize the exception itself. 998f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 999f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If we already opened it and we're continuing to overflow, abort the VM. 1000f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 1001f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We have to leave the "reserved" area open until the "catch" handler has 1002f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * finished doing its processing. This is because the catch handler may 1003f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * need to resolve classes, which requires calling into the class loader if 1004f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the classes aren't already in the "initiating loader" list. 1005f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 10066ed1a0f396a1857c31b486d3e93ee2dbeb49a6cdAndy McFaddenvoid dvmHandleStackOverflow(Thread* self, const Method* method) 1007f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 1008f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 1009f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Can we make the reserved area available? 1010f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1011f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (self->stackOverflowed) { 1012f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 1013f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Already did, nothing to do but bail. 1014f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 101560fc806b679a3655c228b4093058c59941a49cfeDan Bornstein LOGE("DalvikVM: double-overflow of stack in threadid=%d; aborting", 1016f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->threadId); 1017f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmDumpThread(self, false); 1018f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmAbort(); 1019f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1020f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1021f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* open it up to the full range */ 102260fc806b679a3655c228b4093058c59941a49cfeDan Bornstein LOGI("threadid=%d: stack overflow on call to %s.%s:%s", 10236ed1a0f396a1857c31b486d3e93ee2dbeb49a6cdAndy McFadden self->threadId, 10246ed1a0f396a1857c31b486d3e93ee2dbeb49a6cdAndy McFadden method->clazz->descriptor, method->name, method->shorty); 102530bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee StackSaveArea* saveArea = SAVEAREA_FROM_FP(self->interpSave.curFrame); 102660fc806b679a3655c228b4093058c59941a49cfeDan Bornstein LOGI(" method requires %d+%d+%d=%d bytes, fp is %p (%d left)", 10276ed1a0f396a1857c31b486d3e93ee2dbeb49a6cdAndy McFadden method->registersSize * 4, sizeof(StackSaveArea), method->outsSize * 4, 10286ed1a0f396a1857c31b486d3e93ee2dbeb49a6cdAndy McFadden (method->registersSize + method->outsSize) * 4 + sizeof(StackSaveArea), 10296ed1a0f396a1857c31b486d3e93ee2dbeb49a6cdAndy McFadden saveArea, (u1*) saveArea - self->interpStackEnd); 103060fc806b679a3655c228b4093058c59941a49cfeDan Bornstein LOGI(" expanding stack end (%p to %p)", self->interpStackEnd, 1031f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->interpStackStart - self->interpStackSize); 1032f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project //dvmDumpThread(self, false); 1033f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->interpStackEnd = self->interpStackStart - self->interpStackSize; 1034f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->stackOverflowed = true; 1035f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1036f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 1037f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If we were trying to throw an exception when the stack overflowed, 1038f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * we will blow up when doing the class lookup on StackOverflowError 1039f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * because of the pending exception. So, we clear it and make it 1040f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the cause of the SOE. 1041f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1042f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Object* excep = dvmGetException(self); 1043f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (excep != NULL) { 104460fc806b679a3655c228b4093058c59941a49cfeDan Bornstein LOGW("Stack overflow while throwing exception"); 1045f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmClearException(self); 1046f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 10470b8b293f228b3d341054bc1fad8a92d6e533b4ddDan Bornstein dvmThrowChainedException(gDvm.exStackOverflowError, NULL, excep); 1048f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1049f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1050f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 1051f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Reduce the available stack size. By this point we should have finished 1052f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * our overflow processing. 1053f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 10544fbba1f95b3e27bdc5f5572bb0420b5f928aa54eAndy McFaddenvoid dvmCleanupStackOverflow(Thread* self, const Object* exception) 1055f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 1056f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const u1* newStackEnd; 1057f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1058f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(self->stackOverflowed); 1059f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 106032bb3da6f05959749161ce7f9103027f11597fe3Dan Bornstein if (exception->clazz != gDvm.exStackOverflowError) { 10614fbba1f95b3e27bdc5f5572bb0420b5f928aa54eAndy McFadden /* exception caused during SOE, not the SOE itself */ 10624fbba1f95b3e27bdc5f5572bb0420b5f928aa54eAndy McFadden return; 10634fbba1f95b3e27bdc5f5572bb0420b5f928aa54eAndy McFadden } 10644fbba1f95b3e27bdc5f5572bb0420b5f928aa54eAndy McFadden 1065f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project newStackEnd = (self->interpStackStart - self->interpStackSize) 1066f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project + STACK_OVERFLOW_RESERVE; 106730bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee if ((u1*)self->interpSave.curFrame <= newStackEnd) { 106860fc806b679a3655c228b4093058c59941a49cfeDan Bornstein LOGE("Can't shrink stack: curFrame is in reserved area (%p %p)", 106930bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee self->interpStackEnd, self->interpSave.curFrame); 1070f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmDumpThread(self, false); 1071f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmAbort(); 1072f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1073f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1074f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->interpStackEnd = newStackEnd; 1075f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->stackOverflowed = false; 1076f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 107760fc806b679a3655c228b4093058c59941a49cfeDan Bornstein LOGI("Shrank stack (to %p, curFrame is %p)", self->interpStackEnd, 107830bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee self->interpSave.curFrame); 1079f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1080f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1081f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1082f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 1083fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * Extract the object that is the target of a monitor-enter instruction 1084fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * in the top stack frame of "thread". 1085fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * 1086fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * The other thread might be alive, so this has to work carefully. 1087fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * 1088d19988d14f24086ea1bb37cf662c8729ff78e113Andy McFadden * The thread list lock must be held. 1089fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * 1090fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * Returns "true" if we successfully recover the object. "*pOwner" will 1091fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * be NULL if we can't determine the owner for some reason (e.g. race 1092fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * condition on ownership transfer). 1093fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden */ 1094fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFaddenstatic bool extractMonitorEnterObject(Thread* thread, Object** pLockObj, 1095fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden Thread** pOwner) 1096fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden{ 109730bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee void* framePtr = thread->interpSave.curFrame; 1098fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden 1099fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro if (framePtr == NULL || dvmIsBreakFrame((u4*)framePtr)) 1100fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden return false; 1101fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden 1102fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden const StackSaveArea* saveArea = SAVEAREA_FROM_FP(framePtr); 1103fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden const Method* method = saveArea->method; 1104fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden const u2* currentPc = saveArea->xtra.currentPc; 1105fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden 1106fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden /* check Method* */ 1107fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden if (!dvmLinearAllocContains(method, sizeof(Method))) { 110860fc806b679a3655c228b4093058c59941a49cfeDan Bornstein LOGD("ExtrMon: method %p not valid", method); 1109fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden return false; 1110fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden } 1111fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden 1112fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden /* check currentPc */ 1113fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden u4 insnsSize = dvmGetMethodInsnsSize(method); 1114fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden if (currentPc < method->insns || 1115fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden currentPc >= method->insns + insnsSize) 1116fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden { 111760fc806b679a3655c228b4093058c59941a49cfeDan Bornstein LOGD("ExtrMon: insns %p not valid (%p - %p)", 1118fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden currentPc, method->insns, method->insns + insnsSize); 1119fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden return false; 1120fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden } 1121fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden 1122fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden /* check the instruction */ 1123fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden if ((*currentPc & 0xff) != OP_MONITOR_ENTER) { 112460fc806b679a3655c228b4093058c59941a49cfeDan Bornstein LOGD("ExtrMon: insn at %p is not monitor-enter (0x%02x)", 1125fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden currentPc, *currentPc & 0xff); 1126fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden return false; 1127fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden } 1128fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden 1129fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden /* get and check the register index */ 1130fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden unsigned int reg = *currentPc >> 8; 1131fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden if (reg >= method->registersSize) { 113260fc806b679a3655c228b4093058c59941a49cfeDan Bornstein LOGD("ExtrMon: invalid register %d (max %d)", 1133fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden reg, method->registersSize); 1134fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden return false; 1135fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden } 1136fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden 1137fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden /* get and check the object in that register */ 1138fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden u4* fp = (u4*) framePtr; 1139fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden Object* obj = (Object*) fp[reg]; 1140fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden if (!dvmIsValidObject(obj)) { 114160fc806b679a3655c228b4093058c59941a49cfeDan Bornstein LOGD("ExtrMon: invalid object %p at %p[%d]", obj, fp, reg); 1142fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden return false; 1143fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden } 1144fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden *pLockObj = obj; 1145fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden 1146fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden /* 1147fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * Try to determine the object's lock holder; it's okay if this fails. 1148fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * 1149fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * We're assuming the thread list lock is already held by this thread. 1150fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * If it's not, we may be living dangerously if we have to scan through 1151fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * the thread list to find a match. (The VM will generally be in a 1152fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * suspended state when executing here, so this is a minor concern 1153fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * unless we're dumping while threads are running, in which case there's 1154fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * a good chance of stuff blowing up anyway.) 1155fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden */ 1156fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden *pOwner = dvmGetObjectLockHolder(obj); 1157fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden 1158fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden return true; 1159fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden} 1160fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden 1161fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden/* 1162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Dump stack frames, starting from the specified frame and moving down. 1163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 1164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Each frame holds a pointer to the currently executing method, and the 1165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * saved program counter from the caller ("previous" frame). This means 1166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * we don't have the PC for the current method on the stack, which is 1167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * pretty reasonable since it's in the "PC register" for the VM. Because 1168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * exceptions need to show the correct line number we actually *do* have 1169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * an updated version in the fame's "xtra.currentPc", but it's unreliable. 1170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 1171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Note "framePtr" could be NULL in rare circumstances. 1172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void dumpFrames(const DebugOutputTarget* target, void* framePtr, 1174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Thread* thread) 1175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 1176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const StackSaveArea* saveArea; 1177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const Method* method; 1178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int checkCount = 0; 1179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const u2* currentPc = NULL; 1180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project bool first = true; 1181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 1183d19988d14f24086ea1bb37cf662c8729ff78e113Andy McFadden * We call functions that require us to be holding the thread list lock. 1184d19988d14f24086ea1bb37cf662c8729ff78e113Andy McFadden * It's probable that the caller has already done so, but it's not 1185d19988d14f24086ea1bb37cf662c8729ff78e113Andy McFadden * guaranteed. If it's not locked, lock it now. 1186d19988d14f24086ea1bb37cf662c8729ff78e113Andy McFadden */ 1187d19988d14f24086ea1bb37cf662c8729ff78e113Andy McFadden bool needThreadUnlock = dvmTryLockThreadList(); 1188d19988d14f24086ea1bb37cf662c8729ff78e113Andy McFadden 1189d19988d14f24086ea1bb37cf662c8729ff78e113Andy McFadden /* 1190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The "currentPc" is updated whenever we execute an instruction that 1191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * might throw an exception. Show it here. 1192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1193fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro if (framePtr != NULL && !dvmIsBreakFrame((u4*)framePtr)) { 1194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveArea = SAVEAREA_FROM_FP(framePtr); 1195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (saveArea->xtra.currentPc != NULL) 1197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project currentPc = saveArea->xtra.currentPc; 1198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project while (framePtr != NULL) { 1201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveArea = SAVEAREA_FROM_FP(framePtr); 1202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project method = saveArea->method; 1203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1204fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro if (dvmIsBreakFrame((u4*)framePtr)) { 1205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project //dvmPrintDebugMessage(target, " (break frame)\n"); 1206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 1207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int relPc; 1208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (currentPc != NULL) 1210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project relPc = currentPc - saveArea->method->insns; 1211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project else 1212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project relPc = -1; 1213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 121430bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee char* className = 121530bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee dvmHumanReadableDescriptor(method->clazz->descriptor); 1216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (dvmIsNativeMethod(method)) 1217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmPrintDebugMessage(target, 1218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project " at %s.%s(Native Method)\n", className, method->name); 1219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project else { 1220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmPrintDebugMessage(target, 1221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project " at %s.%s(%s:%s%d)\n", 1222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project className, method->name, dvmGetMethodSourceFile(method), 1223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project (relPc >= 0 && first) ? "~" : "", 1224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project relPc < 0 ? -1 : dvmLineNumFromPC(method, relPc)); 1225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project free(className); 1227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1228fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden if (first) { 1229fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden /* 1230fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * Decorate WAIT and MONITOR threads with some detail on 1231fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * the first frame. 1232fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * 1233fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden * warning: wait status not stable, even in suspend 1234fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden */ 1235fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden if (thread->status == THREAD_WAIT || 1236fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden thread->status == THREAD_TIMED_WAIT) 1237fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden { 1238fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden Monitor* mon = thread->waitMonitor; 1239fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden Object* obj = dvmGetMonitorObject(mon); 1240fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden if (obj != NULL) { 1241d19988d14f24086ea1bb37cf662c8729ff78e113Andy McFadden Thread* joinThread = NULL; 124230bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee className = 124330bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee dvmHumanReadableDescriptor(obj->clazz->descriptor); 1244d19988d14f24086ea1bb37cf662c8729ff78e113Andy McFadden if (strcmp(className, "java.lang.VMThread") == 0) { 1245d19988d14f24086ea1bb37cf662c8729ff78e113Andy McFadden joinThread = dvmGetThreadFromThreadObject(obj); 1246d19988d14f24086ea1bb37cf662c8729ff78e113Andy McFadden } 1247d19988d14f24086ea1bb37cf662c8729ff78e113Andy McFadden if (joinThread == NULL) { 1248d19988d14f24086ea1bb37cf662c8729ff78e113Andy McFadden dvmPrintDebugMessage(target, 1249d19988d14f24086ea1bb37cf662c8729ff78e113Andy McFadden " - waiting on <%p> (a %s)\n", obj, className); 1250d19988d14f24086ea1bb37cf662c8729ff78e113Andy McFadden } else { 1251d19988d14f24086ea1bb37cf662c8729ff78e113Andy McFadden dvmPrintDebugMessage(target, 1252d19988d14f24086ea1bb37cf662c8729ff78e113Andy McFadden " - waiting on <%p> (a %s) tid=%d\n", 1253d19988d14f24086ea1bb37cf662c8729ff78e113Andy McFadden obj, className, joinThread->threadId); 1254d19988d14f24086ea1bb37cf662c8729ff78e113Andy McFadden } 1255fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden free(className); 1256fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden } 1257fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden } else if (thread->status == THREAD_MONITOR) { 1258fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden Object* obj; 1259fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden Thread* owner; 1260fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden if (extractMonitorEnterObject(thread, &obj, &owner)) { 126130bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee className = 126230bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee dvmHumanReadableDescriptor(obj->clazz->descriptor); 1263fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden if (owner != NULL) { 1264fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden char* threadName = dvmGetThreadName(owner); 1265fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden dvmPrintDebugMessage(target, 1266fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden " - waiting to lock <%p> (a %s) held by threadid=%d (%s)\n", 1267fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden obj, className, owner->threadId, threadName); 1268fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden free(threadName); 1269fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden } else { 1270fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden dvmPrintDebugMessage(target, 1271fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden " - waiting to lock <%p> (a %s) held by ???\n", 1272fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden obj, className); 1273fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden } 1274fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden free(className); 1275fd54266907c3046339b48748f63afa32ee3ab4e1Andy McFadden } 1276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 1281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get saved PC for previous frame. There's no savedPc in a "break" 1282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * frame, because that represents native or interpreted code 1283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * invoked by the VM. The saved PC is sitting in the "PC register", 1284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * a local variable on the native stack. 1285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project currentPc = saveArea->savedPc; 1287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project first = false; 1289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 12900083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden if (saveArea->prevFrame != NULL && saveArea->prevFrame <= framePtr) { 129160fc806b679a3655c228b4093058c59941a49cfeDan Bornstein LOGW("Warning: loop in stack trace at frame %d (%p -> %p)", 12920083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden checkCount, framePtr, saveArea->prevFrame); 12930083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden break; 12940083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden } 1295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project framePtr = saveArea->prevFrame; 1296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project checkCount++; 12980083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden if (checkCount > 300) { 1299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmPrintDebugMessage(target, 1300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project " ***** printed %d frames, not showing any more\n", 1301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project checkCount); 1302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 1303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmPrintDebugMessage(target, "\n"); 1306d19988d14f24086ea1bb37cf662c8729ff78e113Andy McFadden 1307d19988d14f24086ea1bb37cf662c8729ff78e113Andy McFadden if (needThreadUnlock) { 1308d19988d14f24086ea1bb37cf662c8729ff78e113Andy McFadden dvmUnlockThreadList(); 1309d19988d14f24086ea1bb37cf662c8729ff78e113Andy McFadden } 1310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 1314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Dump the stack for the specified thread. 1315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmDumpThreadStack(const DebugOutputTarget* target, Thread* thread) 1317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 131830bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee dumpFrames(target, thread->interpSave.curFrame, thread); 1319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 1322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Dump the stack for the specified thread, which is still running. 1323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 1324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This is very dangerous, because stack frames are being pushed on and 1325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * popped off, and if the thread exits we'll be looking at freed memory. 1326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The plan here is to take a snapshot of the stack and then dump that 1327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * to try to minimize the chances of catching it mid-update. This should 1328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * work reasonably well on a single-CPU system. 1329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 1330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * There is a small chance that calling here will crash the VM. 1331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmDumpRunningThreadStack(const DebugOutputTarget* target, Thread* thread) 1333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 1334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project StackSaveArea* saveArea; 1335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const u1* origStack; 1336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project u1* stackCopy = NULL; 1337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int origSize, fpOffset; 1338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project void* fp; 1339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int depthLimit = 200; 1340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 134130bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee if (thread == NULL || thread->interpSave.curFrame == NULL) { 1342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmPrintDebugMessage(target, 1343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "DumpRunning: Thread at %p has no curFrame (threadid=%d)\n", 1344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project thread, (thread != NULL) ? thread->threadId : 0); 1345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return; 1346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* wait for a full quantum */ 1349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project sched_yield(); 1350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* copy the info we need, then the stack itself */ 1352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project origSize = thread->interpStackSize; 1353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project origStack = (const u1*) thread->interpStackStart - origSize; 1354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stackCopy = (u1*) malloc(origSize); 135530bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee fpOffset = (u1*) thread->interpSave.curFrame - origStack; 1356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project memcpy(stackCopy, origStack, origSize); 1357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 1359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Run through the stack and rewrite the "prev" pointers. 1360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 136160fc806b679a3655c228b4093058c59941a49cfeDan Bornstein //LOGI("DR: fpOff=%d (from %p %p)",fpOffset, origStack, 136230bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee // thread->interpSave.curFrame); 1363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project fp = stackCopy + fpOffset; 1364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project while (true) { 1365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int prevOffset; 1366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (depthLimit-- < 0) { 1368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* we're probably screwed */ 1369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmPrintDebugMessage(target, "DumpRunning: depth limit hit\n"); 1370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmAbort(); 1371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveArea = SAVEAREA_FROM_FP(fp); 1373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (saveArea->prevFrame == NULL) 1374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 1375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project prevOffset = (u1*) saveArea->prevFrame - origStack; 1377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (prevOffset < 0 || prevOffset > origSize) { 1378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmPrintDebugMessage(target, 1379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "DumpRunning: bad offset found: %d (from %p %p)\n", 1380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project prevOffset, origStack, saveArea->prevFrame); 1381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveArea->prevFrame = NULL; 1382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 1383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 138530bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee saveArea->prevFrame = (u4*)(stackCopy + prevOffset); 1386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project fp = saveArea->prevFrame; 1387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 1390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We still need to pass the Thread for some monitor wait stuff. 1391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dumpFrames(target, stackCopy + fpOffset, thread); 1393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project free(stackCopy); 1394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1395