12ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project/* 22ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 32ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * 42ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 52ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * you may not use this file except in compliance with the License. 62ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * You may obtain a copy of the License at 72ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * 82ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 92ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * 102ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software 112ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 122ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 132ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * See the License for the specific language governing permissions and 142ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * limitations under the License. 152ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */ 1689c1feb0a69a7707b271086e749975b3f7acacf7The Android Open Source Project 172ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project/* 182ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Main interpreter entry point and support functions. 192ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * 202ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * The entry point selects the "standard" or "debug" interpreter and 212ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * facilitates switching between them. The standard interpreter may 222ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * use the "fast" or "portable" implementation. 232ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * 240d615c3ce5bf97ae65b9347ee77968f38620d5e8Andy McFadden * Some debugger support functions are included here. 252ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */ 262ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#include "Dalvik.h" 272ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#include "interp/InterpDefs.h" 289a3147c7412f4794434b4c2604aa2ba784867774buzbee#if defined(WITH_JIT) 299a3147c7412f4794434b4c2604aa2ba784867774buzbee#include "interp/Jit.h" 309a3147c7412f4794434b4c2604aa2ba784867774buzbee#endif 312ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project 322ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project 332ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project/* 342ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * =========================================================================== 352ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Debugger support 362ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * =========================================================================== 372ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */ 382ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project 3996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden// fwd 401e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapirostatic BreakpointSet* dvmBreakpointSetAlloc(); 4196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFaddenstatic void dvmBreakpointSetFree(BreakpointSet* pSet); 4296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden 431813ab265f691e93401c7307c0b34247842ab35eCarl Shapiro#if defined(WITH_JIT) 441813ab265f691e93401c7307c0b34247842ab35eCarl Shapiro/* Target-specific save/restore */ 451813ab265f691e93401c7307c0b34247842ab35eCarl Shapiroextern "C" void dvmJitCalleeSave(double *saveArea); 461813ab265f691e93401c7307c0b34247842ab35eCarl Shapiroextern "C" void dvmJitCalleeRestore(double *saveArea); 471813ab265f691e93401c7307c0b34247842ab35eCarl Shapiro/* Interpreter entry points from compiled code */ 481813ab265f691e93401c7307c0b34247842ab35eCarl Shapiroextern "C" void dvmJitToInterpNormal(); 491813ab265f691e93401c7307c0b34247842ab35eCarl Shapiroextern "C" void dvmJitToInterpNoChain(); 501813ab265f691e93401c7307c0b34247842ab35eCarl Shapiroextern "C" void dvmJitToInterpPunt(); 511813ab265f691e93401c7307c0b34247842ab35eCarl Shapiroextern "C" void dvmJitToInterpSingleStep(); 521813ab265f691e93401c7307c0b34247842ab35eCarl Shapiroextern "C" void dvmJitToInterpTraceSelect(); 531813ab265f691e93401c7307c0b34247842ab35eCarl Shapiro#if defined(WITH_SELF_VERIFICATION) 541813ab265f691e93401c7307c0b34247842ab35eCarl Shapiroextern "C" void dvmJitToInterpBackwardBranch(); 551813ab265f691e93401c7307c0b34247842ab35eCarl Shapiro#endif 561813ab265f691e93401c7307c0b34247842ab35eCarl Shapiro#endif 571813ab265f691e93401c7307c0b34247842ab35eCarl Shapiro 582ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project/* 5996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * Initialize global breakpoint structures. 6096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden */ 611e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapirobool dvmBreakpointStartup() 6296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden{ 6396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden gDvm.breakpointSet = dvmBreakpointSetAlloc(); 6496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden return (gDvm.breakpointSet != NULL); 6596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden} 6696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden 6796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden/* 6896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * Free resources. 6996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden */ 701e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapirovoid dvmBreakpointShutdown() 7196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden{ 7296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden dvmBreakpointSetFree(gDvm.breakpointSet); 7396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden} 7496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden 7596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden 7696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden/* 7796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * This represents a breakpoint inserted in the instruction stream. 782ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * 7996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * The debugger may ask us to create the same breakpoint multiple times. 8096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * We only remove the breakpoint when the last instance is cleared. 8196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden */ 82d862faa2ceae186da5518607505eb942d634ced9Carl Shapirostruct Breakpoint { 83d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden Method* method; /* method we're associated with */ 8496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden u2* addr; /* absolute memory address */ 859a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein u1 originalOpcode; /* original 8-bit opcode value */ 8696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden int setCount; /* #of times this breakpoint was set */ 87d862faa2ceae186da5518607505eb942d634ced9Carl Shapiro}; 8896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden 8996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden/* 9096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * Set of breakpoints. 9196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden */ 9296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFaddenstruct BreakpointSet { 9396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden /* grab lock before reading or writing anything else in here */ 9496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden pthread_mutex_t lock; 9596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden 9696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden /* vector of breakpoint structures */ 9796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden int alloc; 9896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden int count; 9996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden Breakpoint* breakpoints; 10096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden}; 10196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden 10296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden/* 10396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * Initialize a BreakpointSet. Initially empty. 10496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden */ 1051e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapirostatic BreakpointSet* dvmBreakpointSetAlloc() 10696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden{ 10796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden BreakpointSet* pSet = (BreakpointSet*) calloc(1, sizeof(*pSet)); 10896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden 10996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden dvmInitMutex(&pSet->lock); 11096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden /* leave the rest zeroed -- will alloc on first use */ 11196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden 11296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden return pSet; 11396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden} 11496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden 11596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden/* 11696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * Free storage associated with a BreakpointSet. 11796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden */ 11896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFaddenstatic void dvmBreakpointSetFree(BreakpointSet* pSet) 11996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden{ 12096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden if (pSet == NULL) 12196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden return; 12296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden 12396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden free(pSet->breakpoints); 12496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden free(pSet); 12596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden} 12696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden 12796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden/* 12896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * Lock the breakpoint set. 129d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden * 130d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden * It's not currently necessary to switch to VMWAIT in the event of 131d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden * contention, because nothing in here can block. However, it's possible 132d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden * that the bytecode-updater code could become fancier in the future, so 133d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden * we do the trylock dance as a bit of future-proofing. 13496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden */ 13596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFaddenstatic void dvmBreakpointSetLock(BreakpointSet* pSet) 13696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden{ 137d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden if (dvmTryLockMutex(&pSet->lock) != 0) { 138d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden Thread* self = dvmThreadSelf(); 1395617ad30c611f373e16bf10c0feec114faef54efCarl Shapiro ThreadStatus oldStatus = dvmChangeStatus(self, THREAD_VMWAIT); 140d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden dvmLockMutex(&pSet->lock); 141d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden dvmChangeStatus(self, oldStatus); 142d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden } 14396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden} 14496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden 14596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden/* 14696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * Unlock the breakpoint set. 14796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden */ 14896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFaddenstatic void dvmBreakpointSetUnlock(BreakpointSet* pSet) 14996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden{ 15096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden dvmUnlockMutex(&pSet->lock); 15196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden} 15296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden 15396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden/* 15496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * Return the #of breakpoints. 15596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden */ 15696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFaddenstatic int dvmBreakpointSetCount(const BreakpointSet* pSet) 15796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden{ 15896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden return pSet->count; 15996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden} 16096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden 16196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden/* 16296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * See if we already have an entry for this address. 16396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * 16496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * The BreakpointSet's lock must be acquired before calling here. 16596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * 16696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * Returns the index of the breakpoint entry, or -1 if not found. 16796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden */ 16896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFaddenstatic int dvmBreakpointSetFind(const BreakpointSet* pSet, const u2* addr) 16996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden{ 17096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden int i; 17196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden 17296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden for (i = 0; i < pSet->count; i++) { 17396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden Breakpoint* pBreak = &pSet->breakpoints[i]; 17496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden if (pBreak->addr == addr) 17596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden return i; 17696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden } 17796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden 17896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden return -1; 17996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden} 18096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden 18196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden/* 18296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * Retrieve the opcode that was originally at the specified location. 18396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * 18496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * The BreakpointSet's lock must be acquired before calling here. 18596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * 18696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * Returns "true" with the opcode in *pOrig on success. 18796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden */ 1889a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornsteinstatic bool dvmBreakpointSetOriginalOpcode(const BreakpointSet* pSet, 18996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden const u2* addr, u1* pOrig) 19096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden{ 19196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden int idx = dvmBreakpointSetFind(pSet, addr); 19296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden if (idx < 0) 19396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden return false; 19496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden 1959a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein *pOrig = pSet->breakpoints[idx].originalOpcode; 19696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden return true; 19796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden} 19896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden 19996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden/* 200da9dc84a1296a11efce0b656cbc87c7112994d0bAndy McFadden * Check the opcode. If it's a "magic" NOP, indicating the start of 201da9dc84a1296a11efce0b656cbc87c7112994d0bAndy McFadden * switch or array data in the instruction stream, we don't want to set 202da9dc84a1296a11efce0b656cbc87c7112994d0bAndy McFadden * a breakpoint. 203da9dc84a1296a11efce0b656cbc87c7112994d0bAndy McFadden * 204da9dc84a1296a11efce0b656cbc87c7112994d0bAndy McFadden * This can happen because the line number information dx generates 205da9dc84a1296a11efce0b656cbc87c7112994d0bAndy McFadden * associates the switch data with the switch statement's line number, 206da9dc84a1296a11efce0b656cbc87c7112994d0bAndy McFadden * and some debuggers put breakpoints at every address associated with 207da9dc84a1296a11efce0b656cbc87c7112994d0bAndy McFadden * a given line. The result is that the breakpoint stomps on the NOP 208da9dc84a1296a11efce0b656cbc87c7112994d0bAndy McFadden * instruction that doubles as a data table magic number, and an explicit 209da9dc84a1296a11efce0b656cbc87c7112994d0bAndy McFadden * check in the interpreter results in an exception being thrown. 210da9dc84a1296a11efce0b656cbc87c7112994d0bAndy McFadden * 211da9dc84a1296a11efce0b656cbc87c7112994d0bAndy McFadden * We don't want to simply refuse to add the breakpoint to the table, 212da9dc84a1296a11efce0b656cbc87c7112994d0bAndy McFadden * because that confuses the housekeeping. We don't want to reject the 213da9dc84a1296a11efce0b656cbc87c7112994d0bAndy McFadden * debugger's event request, and we want to be sure that there's exactly 214da9dc84a1296a11efce0b656cbc87c7112994d0bAndy McFadden * one un-set operation for every set op. 215da9dc84a1296a11efce0b656cbc87c7112994d0bAndy McFadden */ 216da9dc84a1296a11efce0b656cbc87c7112994d0bAndy McFaddenstatic bool instructionIsMagicNop(const u2* addr) 217da9dc84a1296a11efce0b656cbc87c7112994d0bAndy McFadden{ 218da9dc84a1296a11efce0b656cbc87c7112994d0bAndy McFadden u2 curVal = *addr; 2199a3147c7412f4794434b4c2604aa2ba784867774buzbee return ((GET_OPCODE(curVal)) == OP_NOP && (curVal >> 8) != 0); 220da9dc84a1296a11efce0b656cbc87c7112994d0bAndy McFadden} 221da9dc84a1296a11efce0b656cbc87c7112994d0bAndy McFadden 222da9dc84a1296a11efce0b656cbc87c7112994d0bAndy McFadden/* 22396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * Add a breakpoint at a specific address. If the address is already 22496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * present in the table, this just increments the count. 22596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * 22696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * For a new entry, this will extract and preserve the current opcode from 22796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * the instruction stream, and replace it with a breakpoint opcode. 22896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * 22996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * The BreakpointSet's lock must be acquired before calling here. 23096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * 23196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * Returns "true" on success. 23296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden */ 23396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFaddenstatic bool dvmBreakpointSetAdd(BreakpointSet* pSet, Method* method, 23496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden unsigned int instrOffset) 23596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden{ 23696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden const int kBreakpointGrowth = 10; 23796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden const u2* addr = method->insns + instrOffset; 23896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden int idx = dvmBreakpointSetFind(pSet, addr); 23996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden Breakpoint* pBreak; 24096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden 24196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden if (idx < 0) { 24296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden if (pSet->count == pSet->alloc) { 24396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden int newSize = pSet->alloc + kBreakpointGrowth; 24496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden Breakpoint* newVec; 24596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden 24692c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block ALOGV("+++ increasing breakpoint set size to %d", newSize); 24796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden 24896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden /* pSet->breakpoints will be NULL on first entry */ 249fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro newVec = (Breakpoint*)realloc(pSet->breakpoints, newSize * sizeof(Breakpoint)); 25096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden if (newVec == NULL) 25196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden return false; 25296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden 25396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden pSet->breakpoints = newVec; 25496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden pSet->alloc = newSize; 25596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden } 25696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden 25796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden pBreak = &pSet->breakpoints[pSet->count++]; 258d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden pBreak->method = method; 25996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden pBreak->addr = (u2*)addr; 2609a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein pBreak->originalOpcode = *(u1*)addr; 26196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden pBreak->setCount = 1; 26296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden 26396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden /* 26496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * Change the opcode. We must ensure that the BreakpointSet 26596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * updates happen before we change the opcode. 266d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden * 267d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden * If the method has not been verified, we do NOT insert the 268d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden * breakpoint yet, since that will screw up the verifier. The 269d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden * debugger is allowed to insert breakpoints in unverified code, 270d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden * but since we don't execute unverified code we don't need to 271d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden * alter the bytecode yet. 272d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden * 273c7a12b2fc8270722c7de8d24fd8fa943e5ef1818Andy McFadden * The class init code will "flush" all pending opcode writes 274c7a12b2fc8270722c7de8d24fd8fa943e5ef1818Andy McFadden * before verification completes. 27596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden */ 27696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden assert(*(u1*)addr != OP_BREAKPOINT); 277d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden if (dvmIsClassVerified(method->clazz)) { 27892c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block ALOGV("Class %s verified, adding breakpoint at %p", 279d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden method->clazz->descriptor, addr); 280da9dc84a1296a11efce0b656cbc87c7112994d0bAndy McFadden if (instructionIsMagicNop(addr)) { 28192c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block ALOGV("Refusing to set breakpoint on %04x at %s.%s + %#x", 282da9dc84a1296a11efce0b656cbc87c7112994d0bAndy McFadden *addr, method->clazz->descriptor, method->name, 283da9dc84a1296a11efce0b656cbc87c7112994d0bAndy McFadden instrOffset); 284da9dc84a1296a11efce0b656cbc87c7112994d0bAndy McFadden } else { 2856e10b9aaa72425a4825a25f0043533d0c6fdbba4Andy McFadden ANDROID_MEMBAR_FULL(); 286da9dc84a1296a11efce0b656cbc87c7112994d0bAndy McFadden dvmDexChangeDex1(method->clazz->pDvmDex, (u1*)addr, 287da9dc84a1296a11efce0b656cbc87c7112994d0bAndy McFadden OP_BREAKPOINT); 288da9dc84a1296a11efce0b656cbc87c7112994d0bAndy McFadden } 289d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden } else { 29092c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block ALOGV("Class %s NOT verified, deferring breakpoint at %p", 291d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden method->clazz->descriptor, addr); 292d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden } 29396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden } else { 294d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden /* 295c7a12b2fc8270722c7de8d24fd8fa943e5ef1818Andy McFadden * Breakpoint already exists, just increase the count. 296d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden */ 297c7a12b2fc8270722c7de8d24fd8fa943e5ef1818Andy McFadden pBreak = &pSet->breakpoints[idx]; 298c7a12b2fc8270722c7de8d24fd8fa943e5ef1818Andy McFadden pBreak->setCount++; 29996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden } 30096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden 30196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden return true; 30296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden} 30396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden 30496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden/* 30596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * Remove one instance of the specified breakpoint. When the count 30696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * reaches zero, the entry is removed from the table, and the original 30796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * opcode is restored. 30896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * 30996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * The BreakpointSet's lock must be acquired before calling here. 31096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden */ 31196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFaddenstatic void dvmBreakpointSetRemove(BreakpointSet* pSet, Method* method, 31296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden unsigned int instrOffset) 31396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden{ 31496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden const u2* addr = method->insns + instrOffset; 31596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden int idx = dvmBreakpointSetFind(pSet, addr); 31696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden 31796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden if (idx < 0) { 31896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden /* breakpoint not found in set -- unexpected */ 31996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden if (*(u1*)addr == OP_BREAKPOINT) { 320c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block ALOGE("Unable to restore breakpoint opcode (%s.%s +%#x)", 32196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden method->clazz->descriptor, method->name, instrOffset); 32296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden dvmAbort(); 32396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden } else { 324e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block ALOGW("Breakpoint was already restored? (%s.%s +%#x)", 32596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden method->clazz->descriptor, method->name, instrOffset); 32696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden } 32796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden } else { 32896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden Breakpoint* pBreak = &pSet->breakpoints[idx]; 32996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden if (pBreak->setCount == 1) { 33096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden /* 33196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * Must restore opcode before removing set entry. 332d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden * 333d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden * If the breakpoint was never flushed, we could be ovewriting 334d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden * a value with the same value. Not a problem, though we 335d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden * could end up causing a copy-on-write here when we didn't 336d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden * need to. (Not worth worrying about.) 33796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden */ 33896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden dvmDexChangeDex1(method->clazz->pDvmDex, (u1*)addr, 3399a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein pBreak->originalOpcode); 3406e10b9aaa72425a4825a25f0043533d0c6fdbba4Andy McFadden ANDROID_MEMBAR_FULL(); 34196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden 34296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden if (idx != pSet->count-1) { 34396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden /* shift down */ 34496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden memmove(&pSet->breakpoints[idx], &pSet->breakpoints[idx+1], 34596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden (pSet->count-1 - idx) * sizeof(pSet->breakpoints[0])); 34696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden } 34796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden pSet->count--; 34896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden pSet->breakpoints[pSet->count].addr = (u2*) 0xdecadead; // debug 34996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden } else { 35096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden pBreak->setCount--; 35196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden assert(pBreak->setCount > 0); 35296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden } 35396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden } 35496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden} 35596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden 35696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden/* 357d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden * Flush any breakpoints associated with methods in "clazz". We want to 358d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden * change the opcode, which might not have happened when the breakpoint 359d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden * was initially set because the class was in the process of being 360d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden * verified. 36196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * 36296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * The BreakpointSet's lock must be acquired before calling here. 36396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden */ 364d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFaddenstatic void dvmBreakpointSetFlush(BreakpointSet* pSet, ClassObject* clazz) 36596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden{ 36696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden int i; 36796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden for (i = 0; i < pSet->count; i++) { 36896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden Breakpoint* pBreak = &pSet->breakpoints[i]; 369d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden if (pBreak->method->clazz == clazz) { 370d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden /* 371d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden * The breakpoint is associated with a method in this class. 372d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden * It might already be there or it might not; either way, 373d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden * flush it out. 374d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden */ 37592c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block ALOGV("Flushing breakpoint at %p for %s", 376d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden pBreak->addr, clazz->descriptor); 377da9dc84a1296a11efce0b656cbc87c7112994d0bAndy McFadden if (instructionIsMagicNop(pBreak->addr)) { 37892c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block ALOGV("Refusing to flush breakpoint on %04x at %s.%s + %#x", 379e3c01dac83e6eea7f82fe81ed89cfbdd9791dbc9Carl Shapiro *pBreak->addr, pBreak->method->clazz->descriptor, 380e3c01dac83e6eea7f82fe81ed89cfbdd9791dbc9Carl Shapiro pBreak->method->name, pBreak->addr - pBreak->method->insns); 381da9dc84a1296a11efce0b656cbc87c7112994d0bAndy McFadden } else { 382da9dc84a1296a11efce0b656cbc87c7112994d0bAndy McFadden dvmDexChangeDex1(clazz->pDvmDex, (u1*)pBreak->addr, 383da9dc84a1296a11efce0b656cbc87c7112994d0bAndy McFadden OP_BREAKPOINT); 384da9dc84a1296a11efce0b656cbc87c7112994d0bAndy McFadden } 38596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden } 38696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden } 38796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden} 38896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden 38996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden 39096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden/* 39196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * Do any debugger-attach-time initialization. 3922ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */ 3931e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapirovoid dvmInitBreakpoints() 3942ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project{ 39596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden /* quick sanity check */ 39696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden BreakpointSet* pSet = gDvm.breakpointSet; 39796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden dvmBreakpointSetLock(pSet); 39896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden if (dvmBreakpointSetCount(pSet) != 0) { 399e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block ALOGW("WARNING: %d leftover breakpoints", dvmBreakpointSetCount(pSet)); 40096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden /* generally not good, but we can keep going */ 40196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden } 40296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden dvmBreakpointSetUnlock(pSet); 4032ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project} 4042ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project 4052ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project/* 4062ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Add an address to the list, putting it in the first non-empty slot. 4072ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * 4082ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Sometimes the debugger likes to add two entries for one breakpoint. 4092ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * We add two entries here, so that we get the right behavior when it's 4102ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * removed twice. 4112ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * 4122ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * This will only be run from the JDWP thread, and it will happen while 4132ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * we are updating the event list, which is synchronized. We're guaranteed 4142ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * to be the only one adding entries, and the lock ensures that nobody 4152ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * will be trying to remove them while we're in here. 4162ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * 4172ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * "addr" is the absolute address of the breakpoint bytecode. 4182ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */ 41996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFaddenvoid dvmAddBreakAddr(Method* method, unsigned int instrOffset) 4202ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project{ 42196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden BreakpointSet* pSet = gDvm.breakpointSet; 42296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden dvmBreakpointSetLock(pSet); 42396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden dvmBreakpointSetAdd(pSet, method, instrOffset); 42496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden dvmBreakpointSetUnlock(pSet); 4252ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project} 4262ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project 4272ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project/* 4282ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Remove an address from the list by setting the entry to NULL. 4292ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * 4302ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * This can be called from the JDWP thread (because the debugger has 4312ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * cancelled the breakpoint) or from an event thread (because it's a 4322ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * single-shot breakpoint, e.g. "run to line"). We only get here as 4332ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * the result of removing an entry from the event list, which is 4342ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * synchronized, so it should not be possible for two threads to be 4352ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * updating breakpoints at the same time. 4362ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */ 43796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFaddenvoid dvmClearBreakAddr(Method* method, unsigned int instrOffset) 4382ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project{ 43996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden BreakpointSet* pSet = gDvm.breakpointSet; 44096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden dvmBreakpointSetLock(pSet); 44196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden dvmBreakpointSetRemove(pSet, method, instrOffset); 44296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden dvmBreakpointSetUnlock(pSet); 4432ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project} 4442ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project 44596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden/* 44696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * Get the original opcode from under a breakpoint. 447fc3d31683a0120ba005f45f98dcbe1001064dafbAndy McFadden * 448fc3d31683a0120ba005f45f98dcbe1001064dafbAndy McFadden * On SMP hardware it's possible one core might try to execute a breakpoint 449fc3d31683a0120ba005f45f98dcbe1001064dafbAndy McFadden * after another core has cleared it. We need to handle the case where 450fc3d31683a0120ba005f45f98dcbe1001064dafbAndy McFadden * there's no entry in the breakpoint set. (The memory barriers in the 451fc3d31683a0120ba005f45f98dcbe1001064dafbAndy McFadden * locks and in the breakpoint update code should ensure that, once we've 452fc3d31683a0120ba005f45f98dcbe1001064dafbAndy McFadden * observed the absence of a breakpoint entry, we will also now observe 453fc3d31683a0120ba005f45f98dcbe1001064dafbAndy McFadden * the restoration of the original opcode. The fact that we're holding 454fc3d31683a0120ba005f45f98dcbe1001064dafbAndy McFadden * the lock prevents other threads from confusing things further.) 45596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden */ 4569a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornsteinu1 dvmGetOriginalOpcode(const u2* addr) 45796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden{ 45896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden BreakpointSet* pSet = gDvm.breakpointSet; 45996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden u1 orig = 0; 46096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden 46196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden dvmBreakpointSetLock(pSet); 4629a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein if (!dvmBreakpointSetOriginalOpcode(pSet, addr, &orig)) { 46396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden orig = *(u1*)addr; 46496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden if (orig == OP_BREAKPOINT) { 465c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block ALOGE("GLITCH: can't find breakpoint, opcode is still set"); 46696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden dvmAbort(); 46796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden } 46896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden } 46996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden dvmBreakpointSetUnlock(pSet); 47096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden 47196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden return orig; 47296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden} 47396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden 47496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden/* 475d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden * Flush any breakpoints associated with methods in "clazz". 47696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * 477d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden * We don't want to modify the bytecode of a method before the verifier 478d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden * gets a chance to look at it, so we postpone opcode replacement until 479d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden * after verification completes. 48096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden */ 481d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFaddenvoid dvmFlushBreakpoints(ClassObject* clazz) 48296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden{ 48396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden BreakpointSet* pSet = gDvm.breakpointSet; 48496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden 485d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden if (pSet == NULL) 486d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden return; 48796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden 488d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden assert(dvmIsClassVerified(clazz)); 489d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden dvmBreakpointSetLock(pSet); 490d22748a8ddc8f6a7d2e82868b46e9a7739f2e8e5Andy McFadden dvmBreakpointSetFlush(pSet, clazz); 49196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden dvmBreakpointSetUnlock(pSet); 49296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden} 49396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden 4942ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project/* 4952ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Add a single step event. Currently this is a global item. 4962ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * 4972ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * We set up some initial values based on the thread's current state. This 4982ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * won't work well if the thread is running, so it's up to the caller to 4992ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * verify that it's suspended. 5002ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * 5012ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * This is only called from the JDWP thread. 5022ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */ 5032ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Projectbool dvmAddSingleStep(Thread* thread, int size, int depth) 5042ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project{ 5052ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project StepControl* pCtrl = &gDvm.stepControl; 5062ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project 5072ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project if (pCtrl->active && thread != pCtrl->thread) { 508e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block ALOGW("WARNING: single-step active for %p; adding %p", 5092ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project pCtrl->thread, thread); 5102ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project 5112ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project /* 5122ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Keep going, overwriting previous. This can happen if you 5132ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * suspend a thread in Object.wait, hit the single-step key, then 5142ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * switch to another thread and do the same thing again. 5152ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * The first thread's step is still pending. 5162ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * 5172ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * TODO: consider making single-step per-thread. Adds to the 5182ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * overhead, but could be useful in rare situations. 5192ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */ 5202ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project } 5212ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project 5221813ab265f691e93401c7307c0b34247842ab35eCarl Shapiro pCtrl->size = static_cast<JdwpStepSize>(size); 5231813ab265f691e93401c7307c0b34247842ab35eCarl Shapiro pCtrl->depth = static_cast<JdwpStepDepth>(depth); 5242ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project pCtrl->thread = thread; 5252ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project 5262ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project /* 5272ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * We may be stepping into or over method calls, or running until we 5282ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * return from the current method. To make this work we need to track 5292ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * the current line, current method, and current stack depth. We need 5302ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * to be checking these after most instructions, notably those that 5312ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * call methods, return from methods, or are on a different line from the 5322ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * previous instruction. 5332ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * 5342ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * We have to start with a snapshot of the current state. If we're in 5352ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * an interpreted method, everything we need is in the current frame. If 5362ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * we're in a native method, possibly with some extra JNI frames pushed 5372ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * on by PushLocalFrame, we want to use the topmost native method. 5382ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */ 5392ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project const StackSaveArea* saveArea; 54030bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee u4* fp; 54130bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee u4* prevFp = NULL; 54238329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng 54330bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee for (fp = thread->interpSave.curFrame; fp != NULL; 54430bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee fp = saveArea->prevFrame) { 5452ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project const Method* method; 5462ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project 5472ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project saveArea = SAVEAREA_FROM_FP(fp); 5482ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project method = saveArea->method; 5492ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project 550fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro if (!dvmIsBreakFrame((u4*)fp) && !dvmIsNativeMethod(method)) 5512ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project break; 5522ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project prevFp = fp; 5532ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project } 5542ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project if (fp == NULL) { 555e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block ALOGW("Unexpected: step req in native-only threadid=%d", 5562ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project thread->threadId); 5572ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project return false; 5582ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project } 5592ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project if (prevFp != NULL) { 5602ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project /* 5612ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * First interpreted frame wasn't the one at the bottom. Break 5622ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * frames are only inserted when calling from native->interp, so we 5632ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * don't need to worry about one being here. 5642ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */ 56592c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block ALOGV("##### init step while in native method"); 5662ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project fp = prevFp; 567fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro assert(!dvmIsBreakFrame((u4*)fp)); 5682ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project assert(dvmIsNativeMethod(SAVEAREA_FROM_FP(fp)->method)); 5692ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project saveArea = SAVEAREA_FROM_FP(fp); 5702ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project } 5712ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project 5722ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project /* 5732ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Pull the goodies out. "xtra.currentPc" should be accurate since 5742ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * we update it on every instruction while the debugger is connected. 5752ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */ 5762ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project pCtrl->method = saveArea->method; 5772ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project // Clear out any old address set 5782ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project if (pCtrl->pAddressSet != NULL) { 5792ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project // (discard const) 5802ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project free((void *)pCtrl->pAddressSet); 5812ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project pCtrl->pAddressSet = NULL; 5822ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project } 5832ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project if (dvmIsNativeMethod(pCtrl->method)) { 5842ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project pCtrl->line = -1; 5852ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project } else { 5862ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project pCtrl->line = dvmLineNumFromPC(saveArea->method, 5872ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project saveArea->xtra.currentPc - saveArea->method->insns); 58838329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng pCtrl->pAddressSet 5892ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project = dvmAddressSetForLine(saveArea->method, pCtrl->line); 5902ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project } 59130bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee pCtrl->frameDepth = 59230bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee dvmComputeVagueFrameDepth(thread, thread->interpSave.curFrame); 5932ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project pCtrl->active = true; 5942ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project 59592c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block ALOGV("##### step init: thread=%p meth=%p '%s' line=%d frameDepth=%d depth=%s size=%s", 5962ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project pCtrl->thread, pCtrl->method, pCtrl->method->name, 5972ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project pCtrl->line, pCtrl->frameDepth, 5982ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project dvmJdwpStepDepthStr(pCtrl->depth), 5992ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project dvmJdwpStepSizeStr(pCtrl->size)); 6002ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project 6012ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project return true; 6022ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project} 6032ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project 6042ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project/* 6052ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Disable a single step event. 6062ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */ 6072ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Projectvoid dvmClearSingleStep(Thread* thread) 6082ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project{ 6092ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project UNUSED_PARAMETER(thread); 6102ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project 6112ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project gDvm.stepControl.active = false; 6122ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project} 6132ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project 6149a3147c7412f4794434b4c2604aa2ba784867774buzbee/* 6159a3147c7412f4794434b4c2604aa2ba784867774buzbee * The interpreter just threw. Handle any special subMode requirements. 61699e3e6e72e3471eb85fc2e405866392b01c080febuzbee * All interpSave state must be valid on entry. 6179a3147c7412f4794434b4c2604aa2ba784867774buzbee */ 61899e3e6e72e3471eb85fc2e405866392b01c080febuzbeevoid dvmReportExceptionThrow(Thread* self, Object* exception) 6199a3147c7412f4794434b4c2604aa2ba784867774buzbee{ 62099e3e6e72e3471eb85fc2e405866392b01c080febuzbee const Method* curMethod = self->interpSave.method; 6219a3147c7412f4794434b4c2604aa2ba784867774buzbee#if defined(WITH_JIT) 6229a3147c7412f4794434b4c2604aa2ba784867774buzbee if (self->interpBreak.ctl.subMode & kSubModeJitTraceBuild) { 62399e3e6e72e3471eb85fc2e405866392b01c080febuzbee dvmJitEndTraceSelect(self, self->interpSave.pc); 6249a3147c7412f4794434b4c2604aa2ba784867774buzbee } 6259a3147c7412f4794434b4c2604aa2ba784867774buzbee if (self->interpBreak.ctl.breakFlags & kInterpSingleStep) { 6269a3147c7412f4794434b4c2604aa2ba784867774buzbee /* Discard any single-step native returns to translation */ 6279a3147c7412f4794434b4c2604aa2ba784867774buzbee self->jitResumeNPC = NULL; 6289a3147c7412f4794434b4c2604aa2ba784867774buzbee } 6299a3147c7412f4794434b4c2604aa2ba784867774buzbee#endif 6309a3147c7412f4794434b4c2604aa2ba784867774buzbee if (self->interpBreak.ctl.subMode & kSubModeDebuggerActive) { 6319a3147c7412f4794434b4c2604aa2ba784867774buzbee void *catchFrame; 63299e3e6e72e3471eb85fc2e405866392b01c080febuzbee int offset = self->interpSave.pc - curMethod->insns; 63399e3e6e72e3471eb85fc2e405866392b01c080febuzbee int catchRelPc = dvmFindCatchBlock(self, offset, exception, 6349a3147c7412f4794434b4c2604aa2ba784867774buzbee true, &catchFrame); 63530bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee dvmDbgPostException(self->interpSave.curFrame, offset, catchFrame, 63699e3e6e72e3471eb85fc2e405866392b01c080febuzbee catchRelPc, exception); 6379a3147c7412f4794434b4c2604aa2ba784867774buzbee } 6389a3147c7412f4794434b4c2604aa2ba784867774buzbee} 6399a3147c7412f4794434b4c2604aa2ba784867774buzbee 6409a3147c7412f4794434b4c2604aa2ba784867774buzbee/* 6419a3147c7412f4794434b4c2604aa2ba784867774buzbee * The interpreter is preparing to do an invoke (both native & normal). 64299e3e6e72e3471eb85fc2e405866392b01c080febuzbee * Handle any special subMode requirements. All interpSave state 64399e3e6e72e3471eb85fc2e405866392b01c080febuzbee * must be valid on entry. 6449a3147c7412f4794434b4c2604aa2ba784867774buzbee */ 6459a3147c7412f4794434b4c2604aa2ba784867774buzbeevoid dvmReportInvoke(Thread* self, const Method* methodToCall) 6469a3147c7412f4794434b4c2604aa2ba784867774buzbee{ 6479a3147c7412f4794434b4c2604aa2ba784867774buzbee TRACE_METHOD_ENTER(self, methodToCall); 6489a3147c7412f4794434b4c2604aa2ba784867774buzbee} 6499a3147c7412f4794434b4c2604aa2ba784867774buzbee 6509a3147c7412f4794434b4c2604aa2ba784867774buzbee/* 6519a3147c7412f4794434b4c2604aa2ba784867774buzbee * The interpreter is preparing to do a native invoke. Handle any 6529a3147c7412f4794434b4c2604aa2ba784867774buzbee * special subMode requirements. NOTE: for a native invoke, 6539a3147c7412f4794434b4c2604aa2ba784867774buzbee * dvmReportInvoke() and dvmReportPreNativeInvoke() will both 65430bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee * be called prior to the invoke. fp is the Dalvik FP of the calling 65530bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee * method. 6569a3147c7412f4794434b4c2604aa2ba784867774buzbee */ 65730bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbeevoid dvmReportPreNativeInvoke(const Method* methodToCall, Thread* self, u4* fp) 6589a3147c7412f4794434b4c2604aa2ba784867774buzbee{ 6599a3147c7412f4794434b4c2604aa2ba784867774buzbee#if defined(WITH_JIT) 6609a3147c7412f4794434b4c2604aa2ba784867774buzbee /* 6619a3147c7412f4794434b4c2604aa2ba784867774buzbee * Actively building a trace? If so, end it now. The trace 6629a3147c7412f4794434b4c2604aa2ba784867774buzbee * builder can't follow into or through a native method. 6639a3147c7412f4794434b4c2604aa2ba784867774buzbee */ 6649a3147c7412f4794434b4c2604aa2ba784867774buzbee if (self->interpBreak.ctl.subMode & kSubModeJitTraceBuild) { 66599e3e6e72e3471eb85fc2e405866392b01c080febuzbee dvmCheckJit(self->interpSave.pc, self); 6669a3147c7412f4794434b4c2604aa2ba784867774buzbee } 6679a3147c7412f4794434b4c2604aa2ba784867774buzbee#endif 6689a3147c7412f4794434b4c2604aa2ba784867774buzbee if (self->interpBreak.ctl.subMode & kSubModeDebuggerActive) { 66930bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee Object* thisPtr = dvmGetThisPtr(self->interpSave.method, fp); 6708bc8bf71a52e17d483021b4c9dc8e735d9bce3edElliott Hughes assert(thisPtr == NULL || dvmIsHeapAddress(thisPtr)); 6719a3147c7412f4794434b4c2604aa2ba784867774buzbee dvmDbgPostLocationEvent(methodToCall, -1, thisPtr, DBG_METHOD_ENTRY); 6729a3147c7412f4794434b4c2604aa2ba784867774buzbee } 6739a3147c7412f4794434b4c2604aa2ba784867774buzbee} 6749a3147c7412f4794434b4c2604aa2ba784867774buzbee 6759a3147c7412f4794434b4c2604aa2ba784867774buzbee/* 6769a3147c7412f4794434b4c2604aa2ba784867774buzbee * The interpreter has returned from a native invoke. Handle any 67730bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee * special subMode requirements. fp is the Dalvik FP of the calling 67830bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee * method. 6799a3147c7412f4794434b4c2604aa2ba784867774buzbee */ 68030bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbeevoid dvmReportPostNativeInvoke(const Method* methodToCall, Thread* self, u4* fp) 6819a3147c7412f4794434b4c2604aa2ba784867774buzbee{ 6829a3147c7412f4794434b4c2604aa2ba784867774buzbee if (self->interpBreak.ctl.subMode & kSubModeDebuggerActive) { 68330bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee Object* thisPtr = dvmGetThisPtr(self->interpSave.method, fp); 6848bc8bf71a52e17d483021b4c9dc8e735d9bce3edElliott Hughes assert(thisPtr == NULL || dvmIsHeapAddress(thisPtr)); 6859a3147c7412f4794434b4c2604aa2ba784867774buzbee dvmDbgPostLocationEvent(methodToCall, -1, thisPtr, DBG_METHOD_EXIT); 6869a3147c7412f4794434b4c2604aa2ba784867774buzbee } 6879a3147c7412f4794434b4c2604aa2ba784867774buzbee if (self->interpBreak.ctl.subMode & kSubModeMethodTrace) { 6889a3147c7412f4794434b4c2604aa2ba784867774buzbee dvmFastNativeMethodTraceExit(methodToCall, self); 6899a3147c7412f4794434b4c2604aa2ba784867774buzbee } 6909a3147c7412f4794434b4c2604aa2ba784867774buzbee} 6919a3147c7412f4794434b4c2604aa2ba784867774buzbee 6929a3147c7412f4794434b4c2604aa2ba784867774buzbee/* 6939a3147c7412f4794434b4c2604aa2ba784867774buzbee * The interpreter has returned from a normal method. Handle any special 69499e3e6e72e3471eb85fc2e405866392b01c080febuzbee * subMode requirements. All interpSave state must be valid on entry. 6959a3147c7412f4794434b4c2604aa2ba784867774buzbee */ 69699e3e6e72e3471eb85fc2e405866392b01c080febuzbeevoid dvmReportReturn(Thread* self) 6979a3147c7412f4794434b4c2604aa2ba784867774buzbee{ 6989a3147c7412f4794434b4c2604aa2ba784867774buzbee TRACE_METHOD_EXIT(self, self->interpSave.method); 6999a3147c7412f4794434b4c2604aa2ba784867774buzbee#if defined(WITH_JIT) 70030bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee if (dvmIsBreakFrame(self->interpSave.curFrame) && 7019a3147c7412f4794434b4c2604aa2ba784867774buzbee (self->interpBreak.ctl.subMode & kSubModeJitTraceBuild)) { 70299e3e6e72e3471eb85fc2e405866392b01c080febuzbee dvmCheckJit(self->interpSave.pc, self); 7039a3147c7412f4794434b4c2604aa2ba784867774buzbee } 7049a3147c7412f4794434b4c2604aa2ba784867774buzbee#endif 7059a3147c7412f4794434b4c2604aa2ba784867774buzbee} 7069a3147c7412f4794434b4c2604aa2ba784867774buzbee 7079a3147c7412f4794434b4c2604aa2ba784867774buzbee/* 7089a3147c7412f4794434b4c2604aa2ba784867774buzbee * Update the debugger on interesting events, such as hitting a breakpoint 7099a3147c7412f4794434b4c2604aa2ba784867774buzbee * or a single-step point. This is called from the top of the interpreter 7109a3147c7412f4794434b4c2604aa2ba784867774buzbee * loop, before the current instruction is processed. 7119a3147c7412f4794434b4c2604aa2ba784867774buzbee * 7129a3147c7412f4794434b4c2604aa2ba784867774buzbee * Set "methodEntry" if we've just entered the method. This detects 7139a3147c7412f4794434b4c2604aa2ba784867774buzbee * method exit by checking to see if the next instruction is "return". 7149a3147c7412f4794434b4c2604aa2ba784867774buzbee * 7159a3147c7412f4794434b4c2604aa2ba784867774buzbee * This can't catch native method entry/exit, so we have to handle that 7169a3147c7412f4794434b4c2604aa2ba784867774buzbee * at the point of invocation. We also need to catch it in dvmCallMethod 7179a3147c7412f4794434b4c2604aa2ba784867774buzbee * if we want to capture native->native calls made through JNI. 7189a3147c7412f4794434b4c2604aa2ba784867774buzbee * 7199a3147c7412f4794434b4c2604aa2ba784867774buzbee * Notes to self: 7209a3147c7412f4794434b4c2604aa2ba784867774buzbee * - Don't want to switch to VMWAIT while posting events to the debugger. 7219a3147c7412f4794434b4c2604aa2ba784867774buzbee * Let the debugger code decide if we need to change state. 7229a3147c7412f4794434b4c2604aa2ba784867774buzbee * - We may want to check for debugger-induced thread suspensions on 7239a3147c7412f4794434b4c2604aa2ba784867774buzbee * every instruction. That would make a "suspend all" more responsive 7249a3147c7412f4794434b4c2604aa2ba784867774buzbee * and reduce the chances of multiple simultaneous events occurring. 7259a3147c7412f4794434b4c2604aa2ba784867774buzbee * However, it could change the behavior some. 7269a3147c7412f4794434b4c2604aa2ba784867774buzbee * 7279a3147c7412f4794434b4c2604aa2ba784867774buzbee * TODO: method entry/exit events are probably less common than location 7289a3147c7412f4794434b4c2604aa2ba784867774buzbee * breakpoints. We may be able to speed things up a bit if we don't query 7299a3147c7412f4794434b4c2604aa2ba784867774buzbee * the event list unless we know there's at least one lurking within. 7309a3147c7412f4794434b4c2604aa2ba784867774buzbee */ 73199e3e6e72e3471eb85fc2e405866392b01c080febuzbeestatic void updateDebugger(const Method* method, const u2* pc, const u4* fp, 732e71474621b968a9bc649d067155d31213f5764a9buzbee Thread* self) 7339a3147c7412f4794434b4c2604aa2ba784867774buzbee{ 7349a3147c7412f4794434b4c2604aa2ba784867774buzbee int eventFlags = 0; 7359a3147c7412f4794434b4c2604aa2ba784867774buzbee 7369a3147c7412f4794434b4c2604aa2ba784867774buzbee /* 7379a3147c7412f4794434b4c2604aa2ba784867774buzbee * Update xtra.currentPc on every instruction. We need to do this if 7389a3147c7412f4794434b4c2604aa2ba784867774buzbee * there's a chance that we could get suspended. This can happen if 7399a3147c7412f4794434b4c2604aa2ba784867774buzbee * eventFlags != 0 here, or somebody manually requests a suspend 7409a3147c7412f4794434b4c2604aa2ba784867774buzbee * (which gets handled at PERIOD_CHECKS time). One place where this 7419a3147c7412f4794434b4c2604aa2ba784867774buzbee * needs to be correct is in dvmAddSingleStep(). 7429a3147c7412f4794434b4c2604aa2ba784867774buzbee */ 7439a3147c7412f4794434b4c2604aa2ba784867774buzbee dvmExportPC(pc, fp); 7449a3147c7412f4794434b4c2604aa2ba784867774buzbee 745e71474621b968a9bc649d067155d31213f5764a9buzbee if (self->debugIsMethodEntry) { 7469a3147c7412f4794434b4c2604aa2ba784867774buzbee eventFlags |= DBG_METHOD_ENTRY; 747e71474621b968a9bc649d067155d31213f5764a9buzbee self->debugIsMethodEntry = false; 748e71474621b968a9bc649d067155d31213f5764a9buzbee } 7499a3147c7412f4794434b4c2604aa2ba784867774buzbee 7509a3147c7412f4794434b4c2604aa2ba784867774buzbee /* 7519a3147c7412f4794434b4c2604aa2ba784867774buzbee * See if we have a breakpoint here. 7529a3147c7412f4794434b4c2604aa2ba784867774buzbee * 7539a3147c7412f4794434b4c2604aa2ba784867774buzbee * Depending on the "mods" associated with event(s) on this address, 7549a3147c7412f4794434b4c2604aa2ba784867774buzbee * we may or may not actually send a message to the debugger. 7559a3147c7412f4794434b4c2604aa2ba784867774buzbee */ 7569a3147c7412f4794434b4c2604aa2ba784867774buzbee if (GET_OPCODE(*pc) == OP_BREAKPOINT) { 75792c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block ALOGV("+++ breakpoint hit at %p", pc); 7589a3147c7412f4794434b4c2604aa2ba784867774buzbee eventFlags |= DBG_BREAKPOINT; 7599a3147c7412f4794434b4c2604aa2ba784867774buzbee } 7609a3147c7412f4794434b4c2604aa2ba784867774buzbee 7619a3147c7412f4794434b4c2604aa2ba784867774buzbee /* 7629a3147c7412f4794434b4c2604aa2ba784867774buzbee * If the debugger is single-stepping one of our threads, check to 7639a3147c7412f4794434b4c2604aa2ba784867774buzbee * see if we're that thread and we've reached a step point. 7649a3147c7412f4794434b4c2604aa2ba784867774buzbee */ 7659a3147c7412f4794434b4c2604aa2ba784867774buzbee const StepControl* pCtrl = &gDvm.stepControl; 7669a3147c7412f4794434b4c2604aa2ba784867774buzbee if (pCtrl->active && pCtrl->thread == self) { 7679a3147c7412f4794434b4c2604aa2ba784867774buzbee int frameDepth; 7689a3147c7412f4794434b4c2604aa2ba784867774buzbee bool doStop = false; 7699a3147c7412f4794434b4c2604aa2ba784867774buzbee const char* msg = NULL; 7709a3147c7412f4794434b4c2604aa2ba784867774buzbee 7719a3147c7412f4794434b4c2604aa2ba784867774buzbee assert(!dvmIsNativeMethod(method)); 7729a3147c7412f4794434b4c2604aa2ba784867774buzbee 7739a3147c7412f4794434b4c2604aa2ba784867774buzbee if (pCtrl->depth == SD_INTO) { 7749a3147c7412f4794434b4c2604aa2ba784867774buzbee /* 7759a3147c7412f4794434b4c2604aa2ba784867774buzbee * Step into method calls. We break when the line number 7769a3147c7412f4794434b4c2604aa2ba784867774buzbee * or method pointer changes. If we're in SS_MIN mode, we 7779a3147c7412f4794434b4c2604aa2ba784867774buzbee * always stop. 7789a3147c7412f4794434b4c2604aa2ba784867774buzbee */ 7799a3147c7412f4794434b4c2604aa2ba784867774buzbee if (pCtrl->method != method) { 7809a3147c7412f4794434b4c2604aa2ba784867774buzbee doStop = true; 7819a3147c7412f4794434b4c2604aa2ba784867774buzbee msg = "new method"; 7829a3147c7412f4794434b4c2604aa2ba784867774buzbee } else if (pCtrl->size == SS_MIN) { 7839a3147c7412f4794434b4c2604aa2ba784867774buzbee doStop = true; 7849a3147c7412f4794434b4c2604aa2ba784867774buzbee msg = "new instruction"; 7859a3147c7412f4794434b4c2604aa2ba784867774buzbee } else if (!dvmAddressSetGet( 7869a3147c7412f4794434b4c2604aa2ba784867774buzbee pCtrl->pAddressSet, pc - method->insns)) { 7879a3147c7412f4794434b4c2604aa2ba784867774buzbee doStop = true; 7889a3147c7412f4794434b4c2604aa2ba784867774buzbee msg = "new line"; 7899a3147c7412f4794434b4c2604aa2ba784867774buzbee } 7909a3147c7412f4794434b4c2604aa2ba784867774buzbee } else if (pCtrl->depth == SD_OVER) { 7919a3147c7412f4794434b4c2604aa2ba784867774buzbee /* 7929a3147c7412f4794434b4c2604aa2ba784867774buzbee * Step over method calls. We break when the line number is 7939a3147c7412f4794434b4c2604aa2ba784867774buzbee * different and the frame depth is <= the original frame 7949a3147c7412f4794434b4c2604aa2ba784867774buzbee * depth. (We can't just compare on the method, because we 7959a3147c7412f4794434b4c2604aa2ba784867774buzbee * might get unrolled past it by an exception, and it's tricky 7969a3147c7412f4794434b4c2604aa2ba784867774buzbee * to identify recursion.) 7979a3147c7412f4794434b4c2604aa2ba784867774buzbee */ 7989a3147c7412f4794434b4c2604aa2ba784867774buzbee frameDepth = dvmComputeVagueFrameDepth(self, fp); 7999a3147c7412f4794434b4c2604aa2ba784867774buzbee if (frameDepth < pCtrl->frameDepth) { 8009a3147c7412f4794434b4c2604aa2ba784867774buzbee /* popped up one or more frames, always trigger */ 8019a3147c7412f4794434b4c2604aa2ba784867774buzbee doStop = true; 8029a3147c7412f4794434b4c2604aa2ba784867774buzbee msg = "method pop"; 8039a3147c7412f4794434b4c2604aa2ba784867774buzbee } else if (frameDepth == pCtrl->frameDepth) { 8049a3147c7412f4794434b4c2604aa2ba784867774buzbee /* same depth, see if we moved */ 8059a3147c7412f4794434b4c2604aa2ba784867774buzbee if (pCtrl->size == SS_MIN) { 8069a3147c7412f4794434b4c2604aa2ba784867774buzbee doStop = true; 8079a3147c7412f4794434b4c2604aa2ba784867774buzbee msg = "new instruction"; 8089a3147c7412f4794434b4c2604aa2ba784867774buzbee } else if (!dvmAddressSetGet(pCtrl->pAddressSet, 8099a3147c7412f4794434b4c2604aa2ba784867774buzbee pc - method->insns)) { 8109a3147c7412f4794434b4c2604aa2ba784867774buzbee doStop = true; 8119a3147c7412f4794434b4c2604aa2ba784867774buzbee msg = "new line"; 8129a3147c7412f4794434b4c2604aa2ba784867774buzbee } 8139a3147c7412f4794434b4c2604aa2ba784867774buzbee } 8149a3147c7412f4794434b4c2604aa2ba784867774buzbee } else { 8159a3147c7412f4794434b4c2604aa2ba784867774buzbee assert(pCtrl->depth == SD_OUT); 8169a3147c7412f4794434b4c2604aa2ba784867774buzbee /* 8179a3147c7412f4794434b4c2604aa2ba784867774buzbee * Return from the current method. We break when the frame 8189a3147c7412f4794434b4c2604aa2ba784867774buzbee * depth pops up. 8199a3147c7412f4794434b4c2604aa2ba784867774buzbee * 8209a3147c7412f4794434b4c2604aa2ba784867774buzbee * This differs from the "method exit" break in that it stops 8219a3147c7412f4794434b4c2604aa2ba784867774buzbee * with the PC at the next instruction in the returned-to 8229a3147c7412f4794434b4c2604aa2ba784867774buzbee * function, rather than the end of the returning function. 8239a3147c7412f4794434b4c2604aa2ba784867774buzbee */ 8249a3147c7412f4794434b4c2604aa2ba784867774buzbee frameDepth = dvmComputeVagueFrameDepth(self, fp); 8259a3147c7412f4794434b4c2604aa2ba784867774buzbee if (frameDepth < pCtrl->frameDepth) { 8269a3147c7412f4794434b4c2604aa2ba784867774buzbee doStop = true; 8279a3147c7412f4794434b4c2604aa2ba784867774buzbee msg = "method pop"; 8289a3147c7412f4794434b4c2604aa2ba784867774buzbee } 8299a3147c7412f4794434b4c2604aa2ba784867774buzbee } 8309a3147c7412f4794434b4c2604aa2ba784867774buzbee 8319a3147c7412f4794434b4c2604aa2ba784867774buzbee if (doStop) { 83292c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block ALOGV("#####S %s", msg); 8339a3147c7412f4794434b4c2604aa2ba784867774buzbee eventFlags |= DBG_SINGLE_STEP; 8349a3147c7412f4794434b4c2604aa2ba784867774buzbee } 8359a3147c7412f4794434b4c2604aa2ba784867774buzbee } 8369a3147c7412f4794434b4c2604aa2ba784867774buzbee 8379a3147c7412f4794434b4c2604aa2ba784867774buzbee /* 8389a3147c7412f4794434b4c2604aa2ba784867774buzbee * Check to see if this is a "return" instruction. JDWP says we should 8399a3147c7412f4794434b4c2604aa2ba784867774buzbee * send the event *after* the code has been executed, but it also says 8409a3147c7412f4794434b4c2604aa2ba784867774buzbee * the location we provide is the last instruction. Since the "return" 8419a3147c7412f4794434b4c2604aa2ba784867774buzbee * instruction has no interesting side effects, we should be safe. 8429a3147c7412f4794434b4c2604aa2ba784867774buzbee * (We can't just move this down to the returnFromMethod label because 8439a3147c7412f4794434b4c2604aa2ba784867774buzbee * we potentially need to combine it with other events.) 8449a3147c7412f4794434b4c2604aa2ba784867774buzbee * 8459a3147c7412f4794434b4c2604aa2ba784867774buzbee * We're also not supposed to generate a method exit event if the method 8469a3147c7412f4794434b4c2604aa2ba784867774buzbee * terminates "with a thrown exception". 8479a3147c7412f4794434b4c2604aa2ba784867774buzbee */ 8489a3147c7412f4794434b4c2604aa2ba784867774buzbee u2 opcode = GET_OPCODE(*pc); 8494fa9a95705253695d257381fdb12311f13d7638aElliott Hughes if (opcode == OP_RETURN_VOID || opcode == OP_RETURN || opcode == OP_RETURN_VOID_BARRIER || 8504fa9a95705253695d257381fdb12311f13d7638aElliott Hughes opcode == OP_RETURN_OBJECT || opcode == OP_RETURN_WIDE) 8519a3147c7412f4794434b4c2604aa2ba784867774buzbee { 8529a3147c7412f4794434b4c2604aa2ba784867774buzbee eventFlags |= DBG_METHOD_EXIT; 8539a3147c7412f4794434b4c2604aa2ba784867774buzbee } 8549a3147c7412f4794434b4c2604aa2ba784867774buzbee 8559a3147c7412f4794434b4c2604aa2ba784867774buzbee /* 8569a3147c7412f4794434b4c2604aa2ba784867774buzbee * If there's something interesting going on, see if it matches one 8579a3147c7412f4794434b4c2604aa2ba784867774buzbee * of the debugger filters. 8589a3147c7412f4794434b4c2604aa2ba784867774buzbee */ 8599a3147c7412f4794434b4c2604aa2ba784867774buzbee if (eventFlags != 0) { 8609a3147c7412f4794434b4c2604aa2ba784867774buzbee Object* thisPtr = dvmGetThisPtr(method, fp); 8618bc8bf71a52e17d483021b4c9dc8e735d9bce3edElliott Hughes if (thisPtr != NULL && !dvmIsHeapAddress(thisPtr)) { 8629a3147c7412f4794434b4c2604aa2ba784867774buzbee /* 8639a3147c7412f4794434b4c2604aa2ba784867774buzbee * TODO: remove this check if we're confident that the "this" 8649a3147c7412f4794434b4c2604aa2ba784867774buzbee * pointer is where it should be -- slows us down, especially 8659a3147c7412f4794434b4c2604aa2ba784867774buzbee * during single-step. 8669a3147c7412f4794434b4c2604aa2ba784867774buzbee */ 8679a3147c7412f4794434b4c2604aa2ba784867774buzbee char* desc = dexProtoCopyMethodDescriptor(&method->prototype); 868c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block ALOGE("HEY: invalid 'this' ptr %p (%s.%s %s)", thisPtr, 8699a3147c7412f4794434b4c2604aa2ba784867774buzbee method->clazz->descriptor, method->name, desc); 8709a3147c7412f4794434b4c2604aa2ba784867774buzbee free(desc); 8719a3147c7412f4794434b4c2604aa2ba784867774buzbee dvmAbort(); 8729a3147c7412f4794434b4c2604aa2ba784867774buzbee } 8739a3147c7412f4794434b4c2604aa2ba784867774buzbee dvmDbgPostLocationEvent(method, pc - method->insns, thisPtr, 8749a3147c7412f4794434b4c2604aa2ba784867774buzbee eventFlags); 8759a3147c7412f4794434b4c2604aa2ba784867774buzbee } 8769a3147c7412f4794434b4c2604aa2ba784867774buzbee} 8772ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project 8782ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project/* 8792ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Recover the "this" pointer from the current interpreted method. "this" 8802ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * is always in "in0" for non-static methods. 8812ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * 8822ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * The "ins" start at (#of registers - #of ins). Note in0 != v0. 8832ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * 8842ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * This works because "dx" guarantees that it will work. It's probably 8852ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * fairly common to have a virtual method that doesn't use its "this" 8862ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * pointer, in which case we're potentially wasting a register. However, 8872ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * the debugger doesn't treat "this" as just another argument. For 8882ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * example, events (such as breakpoints) can be enabled for specific 8892ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * values of "this". There is also a separate StackFrame.ThisObject call 8902ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * in JDWP that is expected to work for any non-native non-static method. 8912ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * 8922ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Because we need it when setting up debugger event filters, we want to 8932ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * be able to do this quickly. 8942ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */ 8952ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source ProjectObject* dvmGetThisPtr(const Method* method, const u4* fp) 8962ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project{ 8972ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project if (dvmIsStaticMethod(method)) 8982ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project return NULL; 8992ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project return (Object*)fp[method->registersSize - method->insSize]; 9002ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project} 9012ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project 9022ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project 9032ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#if defined(WITH_TRACKREF_CHECKS) 9042ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project/* 9052ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Verify that all internally-tracked references have been released. If 9062ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * they haven't, print them and abort the VM. 9072ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * 9082ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * "debugTrackedRefStart" indicates how many refs were on the list when 9092ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * we were first invoked. 9102ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */ 9112ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Projectvoid dvmInterpCheckTrackedRefs(Thread* self, const Method* method, 9122ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project int debugTrackedRefStart) 9132ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project{ 9142ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project if (dvmReferenceTableEntries(&self->internalLocalRefTable) 9152ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project != (size_t) debugTrackedRefStart) 9162ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project { 9172ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project char* desc; 9182ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project Object** top; 9192ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project int count; 9202ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project 9212ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project count = dvmReferenceTableEntries(&self->internalLocalRefTable); 9222ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project 923c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block ALOGE("TRACK: unreleased internal reference (prev=%d total=%d)", 9242ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project debugTrackedRefStart, count); 9252ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project desc = dexProtoCopyMethodDescriptor(&method->prototype); 926c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block ALOGE(" current method is %s.%s %s", method->clazz->descriptor, 9272ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project method->name, desc); 9282ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project free(desc); 9292ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project top = self->internalLocalRefTable.table + debugTrackedRefStart; 9302ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project while (top < self->internalLocalRefTable.nextEntry) { 931c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block ALOGE(" %p (%s)", 9322ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project *top, 9332ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project ((*top)->clazz != NULL) ? (*top)->clazz->descriptor : ""); 9342ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project top++; 9352ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project } 9362ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project dvmDumpThread(self, false); 9372ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project 9382ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project dvmAbort(); 9392ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project } 9404308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block //ALOGI("TRACK OK"); 9412ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project} 9422ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#endif 9432ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project 9442ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project 9452ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#ifdef LOG_INSTR 9462ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project/* 9472ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Dump the v-registers. Sent to the ILOG log tag. 9482ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */ 9492ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Projectvoid dvmDumpRegs(const Method* method, const u4* framePtr, bool inOnly) 9502ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project{ 9512ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project int i, localCount; 9522ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project 9532ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project localCount = method->registersSize - method->insSize; 9542ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project 9551663a6c12fdf4732d7ea0a0406af6085b3c408e4Steve Block ALOG(LOG_VERBOSE, LOG_TAG"i", "Registers (fp=%p):", framePtr); 9562ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project for (i = method->registersSize-1; i >= 0; i--) { 9572ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project if (i >= localCount) { 9581663a6c12fdf4732d7ea0a0406af6085b3c408e4Steve Block ALOG(LOG_VERBOSE, LOG_TAG"i", " v%-2d in%-2d : 0x%08x", 9592ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project i, i-localCount, framePtr[i]); 9602ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project } else { 9612ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project if (inOnly) { 9621663a6c12fdf4732d7ea0a0406af6085b3c408e4Steve Block ALOG(LOG_VERBOSE, LOG_TAG"i", " [...]"); 9632ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project break; 9642ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project } 9652ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project const char* name = ""; 9662ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#if 0 // "locals" structure has changed -- need to rewrite this 9678afa9dfe04354e5b3917e31e3e2772885f507580Elliott Hughes int j; 9682ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project DexFile* pDexFile = method->clazz->pDexFile; 9692ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project const DexCode* pDexCode = dvmGetMethodCode(method); 9702ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project int localsSize = dexGetLocalsSize(pDexFile, pDexCode); 9712ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project const DexLocal* locals = dvmDexGetLocals(pDexFile, pDexCode); 9722ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project for (j = 0; j < localsSize, j++) { 9732ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project if (locals[j].registerNum == (u4) i) { 9742ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project name = dvmDexStringStr(locals[j].pName); 9752ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project break; 9762ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project } 9772ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project } 9782ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#endif 9791663a6c12fdf4732d7ea0a0406af6085b3c408e4Steve Block ALOG(LOG_VERBOSE, LOG_TAG"i", " v%-2d : 0x%08x %s", 9802ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project i, framePtr[i], name); 9812ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project } 9822ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project } 9832ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project} 9842ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#endif 9852ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project 9862ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project 9872ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project/* 9882ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * =========================================================================== 9892ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Entry point and general support functions 9902ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * =========================================================================== 9912ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */ 9922ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project 99338329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng/* 9942ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Find the matching case. Returns the offset to the handler instructions. 9952ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * 9962ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Returns 3 if we don't find a match (it's the size of the packed-switch 9972ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * instruction). 9982ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */ 9992ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Projects4 dvmInterpHandlePackedSwitch(const u2* switchData, s4 testVal) 10002ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project{ 10012ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project const int kInstrLen = 3; 10022ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project u2 size; 10032ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project s4 firstKey; 10042ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project const s4* entries; 10052ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project 10062ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project /* 10072ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Packed switch data format: 10082ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * ushort ident = 0x0100 magic value 10092ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * ushort size number of entries in the table 10102ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * int first_key first (and lowest) switch case value 10112ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * int targets[size] branch targets, relative to switch opcode 10122ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * 10132ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Total size is (4+size*2) 16-bit code units. 10142ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */ 10152ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project if (*switchData++ != kPackedSwitchSignature) { 10162ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project /* should have been caught by verifier */ 1017d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein dvmThrowInternalError("bad packed switch magic"); 10182ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project return kInstrLen; 10192ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project } 10202ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project 10212ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project size = *switchData++; 10222ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project assert(size > 0); 10232ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project 10242ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project firstKey = *switchData++; 10252ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project firstKey |= (*switchData++) << 16; 10262ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project 10272ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project if (testVal < firstKey || testVal >= firstKey + size) { 102860fc806b679a3655c228b4093058c59941a49cfeDan Bornstein LOGVV("Value %d not found in switch (%d-%d)", 10292ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project testVal, firstKey, firstKey+size-1); 10302ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project return kInstrLen; 10312ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project } 10322ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project 10332ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project /* The entries are guaranteed to be aligned on a 32-bit boundary; 10342ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * we can treat them as a native int array. 10352ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */ 10362ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project entries = (const s4*) switchData; 10372ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project assert(((u4)entries & 0x3) == 0); 10382ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project 10392ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project assert(testVal - firstKey >= 0 && testVal - firstKey < size); 104060fc806b679a3655c228b4093058c59941a49cfeDan Bornstein LOGVV("Value %d found in slot %d (goto 0x%02x)", 10412ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project testVal, testVal - firstKey, 10422ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project s4FromSwitchData(&entries[testVal - firstKey])); 10432ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project return s4FromSwitchData(&entries[testVal - firstKey]); 10442ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project} 10452ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project 10462ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project/* 10472ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Find the matching case. Returns the offset to the handler instructions. 10482ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * 10492ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Returns 3 if we don't find a match (it's the size of the sparse-switch 10502ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * instruction). 10512ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */ 10522ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Projects4 dvmInterpHandleSparseSwitch(const u2* switchData, s4 testVal) 10532ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project{ 10542ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project const int kInstrLen = 3; 1055e3c01dac83e6eea7f82fe81ed89cfbdd9791dbc9Carl Shapiro u2 size; 10562ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project const s4* keys; 10572ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project const s4* entries; 10582ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project 10592ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project /* 10602ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Sparse switch data format: 10612ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * ushort ident = 0x0200 magic value 10622ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * ushort size number of entries in the table; > 0 10632ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * int keys[size] keys, sorted low-to-high; 32-bit aligned 10642ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * int targets[size] branch targets, relative to switch opcode 10652ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * 10662ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Total size is (2+size*4) 16-bit code units. 10672ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */ 10682ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project 10692ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project if (*switchData++ != kSparseSwitchSignature) { 10702ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project /* should have been caught by verifier */ 1071d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein dvmThrowInternalError("bad sparse switch magic"); 10722ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project return kInstrLen; 10732ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project } 10742ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project 10752ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project size = *switchData++; 10762ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project assert(size > 0); 107738329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng 10782ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project /* The keys are guaranteed to be aligned on a 32-bit boundary; 10792ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * we can treat them as a native int array. 10802ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */ 10812ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project keys = (const s4*) switchData; 10822ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project assert(((u4)keys & 0x3) == 0); 10832ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project 10842ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project /* The entries are guaranteed to be aligned on a 32-bit boundary; 10852ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * we can treat them as a native int array. 10862ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */ 10872ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project entries = keys + size; 10882ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project assert(((u4)entries & 0x3) == 0); 10892ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project 10902ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project /* 109162f19157a87ed8a5f97b919b92728d9029cc3861Andy McFadden * Binary-search through the array of keys, which are guaranteed to 10922ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * be sorted low-to-high. 10932ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */ 109462f19157a87ed8a5f97b919b92728d9029cc3861Andy McFadden int lo = 0; 109562f19157a87ed8a5f97b919b92728d9029cc3861Andy McFadden int hi = size - 1; 109662f19157a87ed8a5f97b919b92728d9029cc3861Andy McFadden while (lo <= hi) { 109762f19157a87ed8a5f97b919b92728d9029cc3861Andy McFadden int mid = (lo + hi) >> 1; 109862f19157a87ed8a5f97b919b92728d9029cc3861Andy McFadden 109962f19157a87ed8a5f97b919b92728d9029cc3861Andy McFadden s4 foundVal = s4FromSwitchData(&keys[mid]); 110062f19157a87ed8a5f97b919b92728d9029cc3861Andy McFadden if (testVal < foundVal) { 110162f19157a87ed8a5f97b919b92728d9029cc3861Andy McFadden hi = mid - 1; 110262f19157a87ed8a5f97b919b92728d9029cc3861Andy McFadden } else if (testVal > foundVal) { 110362f19157a87ed8a5f97b919b92728d9029cc3861Andy McFadden lo = mid + 1; 110462f19157a87ed8a5f97b919b92728d9029cc3861Andy McFadden } else { 110560fc806b679a3655c228b4093058c59941a49cfeDan Bornstein LOGVV("Value %d found in entry %d (goto 0x%02x)", 110662f19157a87ed8a5f97b919b92728d9029cc3861Andy McFadden testVal, mid, s4FromSwitchData(&entries[mid])); 110762f19157a87ed8a5f97b919b92728d9029cc3861Andy McFadden return s4FromSwitchData(&entries[mid]); 11082ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project } 11092ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project } 11102ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project 111160fc806b679a3655c228b4093058c59941a49cfeDan Bornstein LOGVV("Value %d not found in switch", testVal); 11122ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project return kInstrLen; 11132ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project} 11142ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project 11152ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project/* 11166f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden * Copy data for a fill-array-data instruction. On a little-endian machine 11176f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden * we can just do a memcpy(), on a big-endian system we have work to do. 11186f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden * 11196f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden * The trick here is that dexopt has byte-swapped each code unit, which is 11206f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden * exactly what we want for short/char data. For byte data we need to undo 11216f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden * the swap, and for 4- or 8-byte values we need to swap pieces within 11226f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden * each word. 11236f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden */ 11246f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFaddenstatic void copySwappedArrayData(void* dest, const u2* src, u4 size, u2 width) 11256f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden{ 11266f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden#if __BYTE_ORDER == __LITTLE_ENDIAN 11276f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden memcpy(dest, src, size*width); 11286f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden#else 11296f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden int i; 11306f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden 11316f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden switch (width) { 11326f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden case 1: 11336f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden /* un-swap pairs of bytes as we go */ 11346f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden for (i = (size-1) & ~1; i >= 0; i -= 2) { 11356f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden ((u1*)dest)[i] = ((u1*)src)[i+1]; 11366f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden ((u1*)dest)[i+1] = ((u1*)src)[i]; 11376f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden } 11386f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden /* 11396f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden * "src" is padded to end on a two-byte boundary, but we don't want to 11406f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden * assume "dest" is, so we handle odd length specially. 11416f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden */ 11426f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden if ((size & 1) != 0) { 11436f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden ((u1*)dest)[size-1] = ((u1*)src)[size]; 11446f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden } 11456f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden break; 11466f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden case 2: 11476f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden /* already swapped correctly */ 11486f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden memcpy(dest, src, size*width); 11496f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden break; 11506f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden case 4: 11516f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden /* swap word halves */ 11526f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden for (i = 0; i < (int) size; i++) { 11536f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden ((u4*)dest)[i] = (src[(i << 1) + 1] << 16) | src[i << 1]; 11546f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden } 11556f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden break; 11566f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden case 8: 11576f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden /* swap word halves and words */ 11586f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden for (i = 0; i < (int) (size << 1); i += 2) { 11596f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden ((int*)dest)[i] = (src[(i << 1) + 3] << 16) | src[(i << 1) + 2]; 11606f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden ((int*)dest)[i+1] = (src[(i << 1) + 1] << 16) | src[i << 1]; 11616f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden } 11626f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden break; 11636f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden default: 1164c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block ALOGE("Unexpected width %d in copySwappedArrayData", width); 11656f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden dvmAbort(); 11666f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden break; 11676f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden } 11686f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden#endif 11696f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden} 11706f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden 11716f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden/* 11722ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Fill the array with predefined constant values. 11732ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * 11742ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Returns true if job is completed, otherwise false to indicate that 11752ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * an exception has been thrown. 11762ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */ 117789c1feb0a69a7707b271086e749975b3f7acacf7The Android Open Source Projectbool dvmInterpHandleFillArrayData(ArrayObject* arrayObj, const u2* arrayData) 11782ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project{ 11792ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project u2 width; 11802ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project u4 size; 11812ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project 118289c1feb0a69a7707b271086e749975b3f7acacf7The Android Open Source Project if (arrayObj == NULL) { 1183d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein dvmThrowNullPointerException(NULL); 11842ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project return false; 11852ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project } 11867dc966014df20fea6a4643ce2736922d0a7ee2c8Barry Hayes assert (!IS_CLASS_FLAG_SET(((Object *)arrayObj)->clazz, 11877dc966014df20fea6a4643ce2736922d0a7ee2c8Barry Hayes CLASS_ISOBJECTARRAY)); 118889c1feb0a69a7707b271086e749975b3f7acacf7The Android Open Source Project 11892ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project /* 11902ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Array data table format: 11912ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * ushort ident = 0x0300 magic value 11922ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * ushort width width of each element in the table 11932ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * uint size number of elements in the table 11942ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * ubyte data[size*width] table of data values (may contain a single-byte 11952ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * padding at the end) 11962ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * 11972ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Total size is 4+(width * size + 1)/2 16-bit code units. 11982ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */ 11992ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project if (arrayData[0] != kArrayDataSignature) { 1200d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein dvmThrowInternalError("bad array data magic"); 12012ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project return false; 12022ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project } 12032ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project 12042ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project width = arrayData[1]; 12052ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project size = arrayData[2] | (((u4)arrayData[3]) << 16); 12062ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project 1207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (size > arrayObj->length) { 120847f58250c5177adba475b0b11a36151ac0ce9ab9Dan Bornstein dvmThrowArrayIndexOutOfBoundsException(arrayObj->length, size); 12092ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project return false; 12102ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project } 12116f21450e1e5d43b7c210a989ac24bb445e7e29deAndy McFadden copySwappedArrayData(arrayObj->contents, &arrayData[4], size, width); 12122ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project return true; 12132ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project} 12142ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project 12152ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project/* 12162ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Find the concrete method that corresponds to "methodIdx". The code in 12172ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * "method" is executing invoke-method with "thisClass" as its first argument. 12182ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * 12192ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Returns NULL with an exception raised on failure. 12202ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */ 12212ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source ProjectMethod* dvmInterpFindInterfaceMethod(ClassObject* thisClass, u4 methodIdx, 12222ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project const Method* method, DvmDex* methodClassDex) 12232ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project{ 12242ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project Method* absMethod; 12252ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project Method* methodToCall; 12262ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project int i, vtableIndex; 12272ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project 12282ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project /* 12292ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Resolve the method. This gives us the abstract method from the 12302ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * interface class declaration. 12312ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */ 12322ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project absMethod = dvmDexGetResolvedMethod(methodClassDex, methodIdx); 12332ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project if (absMethod == NULL) { 12342ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project absMethod = dvmResolveInterfaceMethod(method->clazz, methodIdx); 12352ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project if (absMethod == NULL) { 123692c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block ALOGV("+ unknown method"); 12372ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project return NULL; 12382ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project } 12392ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project } 12402ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project 12412ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project /* make sure absMethod->methodIndex means what we think it means */ 12422ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project assert(dvmIsAbstractMethod(absMethod)); 12432ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project 12442ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project /* 12452ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Run through the "this" object's iftable. Find the entry for 12462ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * absMethod's class, then use absMethod->methodIndex to find 12472ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * the method's entry. The value there is the offset into our 12482ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * vtable of the actual method to execute. 12492ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * 12502ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * The verifier does not guarantee that objects stored into 12512ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * interface references actually implement the interface, so this 12522ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * check cannot be eliminated. 12532ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */ 12542ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project for (i = 0; i < thisClass->iftableCount; i++) { 12552ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project if (thisClass->iftable[i].clazz == absMethod->clazz) 12562ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project break; 12572ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project } 12582ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project if (i == thisClass->iftableCount) { 12592ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project /* impossible in verified DEX, need to check for it in unverified */ 126070b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein dvmThrowIncompatibleClassChangeError("interface not implemented"); 12612ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project return NULL; 12622ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project } 12632ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project 12642ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project assert(absMethod->methodIndex < 12652ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project thisClass->iftable[i].clazz->virtualMethodCount); 12662ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project 12672ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project vtableIndex = 12682ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project thisClass->iftable[i].methodIndexArray[absMethod->methodIndex]; 12692ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project assert(vtableIndex >= 0 && vtableIndex < thisClass->vtableCount); 12702ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project methodToCall = thisClass->vtable[vtableIndex]; 12712ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project 12722ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#if 0 12732ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project /* this can happen when there's a stale class file */ 12742ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project if (dvmIsAbstractMethod(methodToCall)) { 1275d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein dvmThrowAbstractMethodError("interface method not implemented"); 12762ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project return NULL; 12772ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project } 12782ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#else 12792ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project assert(!dvmIsAbstractMethod(methodToCall) || 12802ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project methodToCall->nativeFunc != NULL); 12812ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#endif 12822ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project 128360fc806b679a3655c228b4093058c59941a49cfeDan Bornstein LOGVV("+++ interface=%s.%s concrete=%s.%s", 12842ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project absMethod->clazz->descriptor, absMethod->name, 12852ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project methodToCall->clazz->descriptor, methodToCall->name); 12862ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project assert(methodToCall != NULL); 12872ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project 12882ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project return methodToCall; 12892ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project} 12902ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project 12912ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project 1292b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden 1293b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden/* 1294b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden * Helpers for dvmThrowVerificationError(). 1295b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden * 1296b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden * Each returns a newly-allocated string. 1297b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden */ 1298b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden#define kThrowShow_accessFromClass 1 1299b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughesstatic std::string classNameFromIndex(const Method* method, int ref, 1300af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden VerifyErrorRefType refType, int flags) 1301b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden{ 1302b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden const DvmDex* pDvmDex = method->clazz->pDvmDex; 1303af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden if (refType == VERIFY_ERROR_REF_FIELD) { 1304af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden /* get class ID from field ID */ 1305af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden const DexFieldId* pFieldId = dexGetFieldId(pDvmDex->pDexFile, ref); 1306af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden ref = pFieldId->classIdx; 1307af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden } else if (refType == VERIFY_ERROR_REF_METHOD) { 1308af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden /* get class ID from method ID */ 1309af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden const DexMethodId* pMethodId = dexGetMethodId(pDvmDex->pDexFile, ref); 1310af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden ref = pMethodId->classIdx; 1311af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden } 1312af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden 1313b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden const char* className = dexStringByTypeIdx(pDvmDex->pDexFile, ref); 1314b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes std::string dotClassName(dvmHumanReadableDescriptor(className)); 1315b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes if (flags == 0) { 1316b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden return dotClassName; 1317b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes } 1318b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden 1319b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes std::string result; 1320b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden if ((flags & kThrowShow_accessFromClass) != 0) { 1321b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes result += "tried to access class " + dotClassName; 1322b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes result += " from class " + dvmHumanReadableDescriptor(method->clazz->descriptor); 1323b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden } else { 1324b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden assert(false); // should've been caught above 1325b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden } 1326b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden 1327b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden return result; 1328b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden} 1329b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughesstatic std::string fieldNameFromIndex(const Method* method, int ref, 1330af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden VerifyErrorRefType refType, int flags) 1331b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden{ 1332af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden if (refType != VERIFY_ERROR_REF_FIELD) { 1333e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block ALOGW("Expected ref type %d, got %d", VERIFY_ERROR_REF_FIELD, refType); 1334af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden return NULL; /* no message */ 1335af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden } 1336af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden 1337b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes const DvmDex* pDvmDex = method->clazz->pDvmDex; 1338b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes const DexFieldId* pFieldId = dexGetFieldId(pDvmDex->pDexFile, ref); 1339b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes const char* className = dexStringByTypeIdx(pDvmDex->pDexFile, pFieldId->classIdx); 1340b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes const char* fieldName = dexStringById(pDvmDex->pDexFile, pFieldId->nameIdx); 1341b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden 1342b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes std::string dotName(dvmHumanReadableDescriptor(className)); 1343b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden 1344b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden if ((flags & kThrowShow_accessFromClass) != 0) { 1345b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes std::string result; 1346b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes result += "tried to access field "; 1347b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes result += dotName + "." + fieldName; 1348b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes result += " from class "; 1349b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes result += dvmHumanReadableDescriptor(method->clazz->descriptor); 1350b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes return result; 1351b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden } 1352b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes return dotName + "." + fieldName; 1353b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden} 1354b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughesstatic std::string methodNameFromIndex(const Method* method, int ref, 1355af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden VerifyErrorRefType refType, int flags) 1356b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden{ 1357af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden if (refType != VERIFY_ERROR_REF_METHOD) { 1358e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block ALOGW("Expected ref type %d, got %d", VERIFY_ERROR_REF_METHOD,refType); 1359af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden return NULL; /* no message */ 1360af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden } 1361af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden 1362b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes const DvmDex* pDvmDex = method->clazz->pDvmDex; 1363b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes const DexMethodId* pMethodId = dexGetMethodId(pDvmDex->pDexFile, ref); 1364b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes const char* className = dexStringByTypeIdx(pDvmDex->pDexFile, pMethodId->classIdx); 1365b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes const char* methodName = dexStringById(pDvmDex->pDexFile, pMethodId->nameIdx); 1366b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden 1367b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes std::string dotName(dvmHumanReadableDescriptor(className)); 1368b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden 1369b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden if ((flags & kThrowShow_accessFromClass) != 0) { 1370b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden char* desc = dexProtoCopyMethodDescriptor(&method->prototype); 1371b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes std::string result; 1372b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes result += "tried to access method "; 1373b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes result += dotName + "." + methodName + ":" + desc; 1374b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes result += " from class " + dvmHumanReadableDescriptor(method->clazz->descriptor); 1375b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden free(desc); 1376b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes return result; 1377b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden } 1378b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes return dotName + "." + methodName; 1379b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden} 1380b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden 13812ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project/* 13823a1aedbc9777eab6275a360b93b81b079464238eAndy McFadden * Throw an exception for a problem identified by the verifier. 13833a1aedbc9777eab6275a360b93b81b079464238eAndy McFadden * 13843a1aedbc9777eab6275a360b93b81b079464238eAndy McFadden * This is used by the invoke-verification-error instruction. It always 13853a1aedbc9777eab6275a360b93b81b079464238eAndy McFadden * throws an exception. 13863a1aedbc9777eab6275a360b93b81b079464238eAndy McFadden * 1387af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden * "kind" indicates the kind of failure encountered by the verifier. It 1388af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden * has two parts, an error code and an indication of the reference type. 13893a1aedbc9777eab6275a360b93b81b079464238eAndy McFadden */ 1390b51ea11c70602918c42764bfafe92a997d3b1803Andy McFaddenvoid dvmThrowVerificationError(const Method* method, int kind, int ref) 13913a1aedbc9777eab6275a360b93b81b079464238eAndy McFadden{ 13921813ab265f691e93401c7307c0b34247842ab35eCarl Shapiro int errorPart = kind & ~(0xff << kVerifyErrorRefTypeShift); 13931813ab265f691e93401c7307c0b34247842ab35eCarl Shapiro int errorRefPart = kind >> kVerifyErrorRefTypeShift; 13941813ab265f691e93401c7307c0b34247842ab35eCarl Shapiro VerifyError errorKind = static_cast<VerifyError>(errorPart); 13951813ab265f691e93401c7307c0b34247842ab35eCarl Shapiro VerifyErrorRefType refType = static_cast<VerifyErrorRefType>(errorRefPart); 1396a3b3512e99ef51940b0a13e57528bd32803f72b4Dan Bornstein ClassObject* exceptionClass = gDvm.exVerifyError; 1397b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes std::string msg; 1398b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden 1399af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden switch ((VerifyError) errorKind) { 1400b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden case VERIFY_ERROR_NO_CLASS: 1401a3b3512e99ef51940b0a13e57528bd32803f72b4Dan Bornstein exceptionClass = gDvm.exNoClassDefFoundError; 1402af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden msg = classNameFromIndex(method, ref, refType, 0); 1403b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden break; 1404b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden case VERIFY_ERROR_NO_FIELD: 1405a3b3512e99ef51940b0a13e57528bd32803f72b4Dan Bornstein exceptionClass = gDvm.exNoSuchFieldError; 1406af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden msg = fieldNameFromIndex(method, ref, refType, 0); 1407b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden break; 1408b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden case VERIFY_ERROR_NO_METHOD: 1409a3b3512e99ef51940b0a13e57528bd32803f72b4Dan Bornstein exceptionClass = gDvm.exNoSuchMethodError; 1410af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden msg = methodNameFromIndex(method, ref, refType, 0); 1411b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden break; 1412b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden case VERIFY_ERROR_ACCESS_CLASS: 1413a3b3512e99ef51940b0a13e57528bd32803f72b4Dan Bornstein exceptionClass = gDvm.exIllegalAccessError; 1414af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden msg = classNameFromIndex(method, ref, refType, 1415af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden kThrowShow_accessFromClass); 1416b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden break; 1417b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden case VERIFY_ERROR_ACCESS_FIELD: 1418a3b3512e99ef51940b0a13e57528bd32803f72b4Dan Bornstein exceptionClass = gDvm.exIllegalAccessError; 1419af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden msg = fieldNameFromIndex(method, ref, refType, 1420af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden kThrowShow_accessFromClass); 1421b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden break; 1422b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden case VERIFY_ERROR_ACCESS_METHOD: 1423a3b3512e99ef51940b0a13e57528bd32803f72b4Dan Bornstein exceptionClass = gDvm.exIllegalAccessError; 1424af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden msg = methodNameFromIndex(method, ref, refType, 1425af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden kThrowShow_accessFromClass); 1426b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden break; 1427b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden case VERIFY_ERROR_CLASS_CHANGE: 1428a3b3512e99ef51940b0a13e57528bd32803f72b4Dan Bornstein exceptionClass = gDvm.exIncompatibleClassChangeError; 1429af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden msg = classNameFromIndex(method, ref, refType, 0); 1430b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden break; 1431b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden case VERIFY_ERROR_INSTANTIATION: 1432a3b3512e99ef51940b0a13e57528bd32803f72b4Dan Bornstein exceptionClass = gDvm.exInstantiationError; 1433af0e838887d3a2fa76e0d2716e39adf2bb0c01a1Andy McFadden msg = classNameFromIndex(method, ref, refType, 0); 1434b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden break; 1435b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden 1436b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden case VERIFY_ERROR_GENERIC: 1437b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden /* generic VerifyError; use default exception, no message */ 1438b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden break; 1439b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden case VERIFY_ERROR_NONE: 1440b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden /* should never happen; use default exception */ 1441b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden assert(false); 14420de2df09a41ffbe2318dbc9a4daa04dc7966f9b8Elliott Hughes msg = "weird - no error specified"; 1443b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden break; 1444b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden 1445b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden /* no default clause -- want warning if enum updated */ 1446b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden } 1447b51ea11c70602918c42764bfafe92a997d3b1803Andy McFadden 1448b08e2b6017770e887f6072c1520b2d7f2ef6916cElliott Hughes dvmThrowException(exceptionClass, msg.c_str()); 14493a1aedbc9777eab6275a360b93b81b079464238eAndy McFadden} 14503a1aedbc9777eab6275a360b93b81b079464238eAndy McFadden 14513a1aedbc9777eab6275a360b93b81b079464238eAndy McFadden/* 1452cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee * Update interpBreak for a single thread. 1453cb3081f675109049e63380170b60871e8275f9a8buzbee */ 1454cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbeevoid updateInterpBreak(Thread* thread, ExecutionSubModes subMode, bool enable) 1455cb3081f675109049e63380170b60871e8275f9a8buzbee{ 14569a3147c7412f4794434b4c2604aa2ba784867774buzbee InterpBreak oldValue, newValue; 1457cb3081f675109049e63380170b60871e8275f9a8buzbee do { 14589a3147c7412f4794434b4c2604aa2ba784867774buzbee oldValue = newValue = thread->interpBreak; 1459cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee newValue.ctl.breakFlags = kInterpNoBreak; // Assume full reset 1460cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee if (enable) 1461cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee newValue.ctl.subMode |= subMode; 1462cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee else 1463cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee newValue.ctl.subMode &= ~subMode; 1464cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee if (newValue.ctl.subMode & SINGLESTEP_BREAK_MASK) 1465cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee newValue.ctl.breakFlags |= kInterpSingleStep; 1466cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee if (newValue.ctl.subMode & SAFEPOINT_BREAK_MASK) 1467cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee newValue.ctl.breakFlags |= kInterpSafePoint; 146875425b731c514bf90c985275d80aa7886727d83fChris Dearman#ifndef DVM_NO_ASM_INTERP 14699a3147c7412f4794434b4c2604aa2ba784867774buzbee newValue.ctl.curHandlerTable = (newValue.ctl.breakFlags) ? 14709a3147c7412f4794434b4c2604aa2ba784867774buzbee thread->altHandlerTable : thread->mainHandlerTable; 147175425b731c514bf90c985275d80aa7886727d83fChris Dearman#endif 14729a3147c7412f4794434b4c2604aa2ba784867774buzbee } while (dvmQuasiAtomicCas64(oldValue.all, newValue.all, 14739a3147c7412f4794434b4c2604aa2ba784867774buzbee &thread->interpBreak.all) != 0); 14749a3147c7412f4794434b4c2604aa2ba784867774buzbee} 14759a3147c7412f4794434b4c2604aa2ba784867774buzbee 14769a3147c7412f4794434b4c2604aa2ba784867774buzbee/* 1477cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee * Update interpBreak for all threads. 1478cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee */ 1479cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbeevoid updateAllInterpBreak(ExecutionSubModes subMode, bool enable) 1480cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee{ 1481cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee Thread* self = dvmThreadSelf(); 1482cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee Thread* thread; 1483cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee 1484cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee dvmLockThreadList(self); 1485cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee for (thread = gDvm.threadList; thread != NULL; thread = thread->next) { 1486cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee updateInterpBreak(thread, subMode, enable); 1487cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee } 1488cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee dvmUnlockThreadList(); 1489cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee} 1490cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee 1491cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee/* 14929a3147c7412f4794434b4c2604aa2ba784867774buzbee * Update the normal and debugger suspend counts for a thread. 14939a3147c7412f4794434b4c2604aa2ba784867774buzbee * threadSuspendCount must be acquired before calling this to 14949a3147c7412f4794434b4c2604aa2ba784867774buzbee * ensure a clean update of suspendCount, dbgSuspendCount and 1495389e258a5b9b2afb7bfaee3344c615d3310fae4ebuzbee * sumThreadSuspendCount. 14969a3147c7412f4794434b4c2604aa2ba784867774buzbee * 14979a3147c7412f4794434b4c2604aa2ba784867774buzbee * CLEANUP TODO: Currently only the JIT is using sumThreadSuspendCount. 14989a3147c7412f4794434b4c2604aa2ba784867774buzbee * Move under WITH_JIT ifdefs. 14999a3147c7412f4794434b4c2604aa2ba784867774buzbee*/ 15009a3147c7412f4794434b4c2604aa2ba784867774buzbeevoid dvmAddToSuspendCounts(Thread* thread, int delta, int dbgDelta) 15019a3147c7412f4794434b4c2604aa2ba784867774buzbee{ 1502389e258a5b9b2afb7bfaee3344c615d3310fae4ebuzbee thread->suspendCount += delta; 1503389e258a5b9b2afb7bfaee3344c615d3310fae4ebuzbee thread->dbgSuspendCount += dbgDelta; 1504cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee updateInterpBreak(thread, kSubModeSuspendPending, 1505cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee (thread->suspendCount != 0)); 15069a3147c7412f4794434b4c2604aa2ba784867774buzbee // Update the global suspend count total 15079a3147c7412f4794434b4c2604aa2ba784867774buzbee gDvm.sumThreadSuspendCount += delta; 15089a3147c7412f4794434b4c2604aa2ba784867774buzbee} 15099a3147c7412f4794434b4c2604aa2ba784867774buzbee 1510cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee 1511cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbeevoid dvmDisableSubMode(Thread* thread, ExecutionSubModes subMode) 15129a3147c7412f4794434b4c2604aa2ba784867774buzbee{ 1513cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee updateInterpBreak(thread, subMode, false); 1514cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee} 15159a3147c7412f4794434b4c2604aa2ba784867774buzbee 1516cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbeevoid dvmEnableSubMode(Thread* thread, ExecutionSubModes subMode) 1517cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee{ 1518cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee updateInterpBreak(thread, subMode, true); 1519cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee} 1520cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee 1521cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbeevoid dvmEnableAllSubMode(ExecutionSubModes subMode) 1522cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee{ 1523cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee updateAllInterpBreak(subMode, true); 1524cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee} 1525cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee 1526cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbeevoid dvmDisableAllSubMode(ExecutionSubModes subMode) 1527cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee{ 1528cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee updateAllInterpBreak(subMode, false); 1529cb3081f675109049e63380170b60871e8275f9a8buzbee} 1530cb3081f675109049e63380170b60871e8275f9a8buzbee 1531cb3081f675109049e63380170b60871e8275f9a8buzbee/* 153299e3e6e72e3471eb85fc2e405866392b01c080febuzbee * Do a sanity check on interpreter state saved to Thread. 153399e3e6e72e3471eb85fc2e405866392b01c080febuzbee * A failure here doesn't necessarily mean that something is wrong, 153499e3e6e72e3471eb85fc2e405866392b01c080febuzbee * so this code should only be used during development to suggest 153599e3e6e72e3471eb85fc2e405866392b01c080febuzbee * a possible problem. 153699e3e6e72e3471eb85fc2e405866392b01c080febuzbee */ 153799e3e6e72e3471eb85fc2e405866392b01c080febuzbeevoid dvmCheckInterpStateConsistency() 153899e3e6e72e3471eb85fc2e405866392b01c080febuzbee{ 153999e3e6e72e3471eb85fc2e405866392b01c080febuzbee Thread* self = dvmThreadSelf(); 154099e3e6e72e3471eb85fc2e405866392b01c080febuzbee Thread* thread; 154199e3e6e72e3471eb85fc2e405866392b01c080febuzbee uint8_t breakFlags; 154299e3e6e72e3471eb85fc2e405866392b01c080febuzbee uint8_t subMode; 154375425b731c514bf90c985275d80aa7886727d83fChris Dearman#ifndef DVM_NO_ASM_INTERP 154499e3e6e72e3471eb85fc2e405866392b01c080febuzbee void* handlerTable; 154575425b731c514bf90c985275d80aa7886727d83fChris Dearman#endif 154699e3e6e72e3471eb85fc2e405866392b01c080febuzbee 154799e3e6e72e3471eb85fc2e405866392b01c080febuzbee dvmLockThreadList(self); 154899e3e6e72e3471eb85fc2e405866392b01c080febuzbee breakFlags = self->interpBreak.ctl.breakFlags; 154999e3e6e72e3471eb85fc2e405866392b01c080febuzbee subMode = self->interpBreak.ctl.subMode; 155075425b731c514bf90c985275d80aa7886727d83fChris Dearman#ifndef DVM_NO_ASM_INTERP 155199e3e6e72e3471eb85fc2e405866392b01c080febuzbee handlerTable = self->interpBreak.ctl.curHandlerTable; 155275425b731c514bf90c985275d80aa7886727d83fChris Dearman#endif 155399e3e6e72e3471eb85fc2e405866392b01c080febuzbee for (thread = gDvm.threadList; thread != NULL; thread = thread->next) { 155499e3e6e72e3471eb85fc2e405866392b01c080febuzbee if (subMode != thread->interpBreak.ctl.subMode) { 1555062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block ALOGD("Warning: subMode mismatch - %#x:%#x, tid[%d]", 155699e3e6e72e3471eb85fc2e405866392b01c080febuzbee subMode,thread->interpBreak.ctl.subMode,thread->threadId); 155799e3e6e72e3471eb85fc2e405866392b01c080febuzbee } 155899e3e6e72e3471eb85fc2e405866392b01c080febuzbee if (breakFlags != thread->interpBreak.ctl.breakFlags) { 1559062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block ALOGD("Warning: breakFlags mismatch - %#x:%#x, tid[%d]", 156099e3e6e72e3471eb85fc2e405866392b01c080febuzbee breakFlags,thread->interpBreak.ctl.breakFlags,thread->threadId); 156199e3e6e72e3471eb85fc2e405866392b01c080febuzbee } 156275425b731c514bf90c985275d80aa7886727d83fChris Dearman#ifndef DVM_NO_ASM_INTERP 156399e3e6e72e3471eb85fc2e405866392b01c080febuzbee if (handlerTable != thread->interpBreak.ctl.curHandlerTable) { 1564062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block ALOGD("Warning: curHandlerTable mismatch - %#x:%#x, tid[%d]", 156599e3e6e72e3471eb85fc2e405866392b01c080febuzbee (int)handlerTable,(int)thread->interpBreak.ctl.curHandlerTable, 156699e3e6e72e3471eb85fc2e405866392b01c080febuzbee thread->threadId); 156799e3e6e72e3471eb85fc2e405866392b01c080febuzbee } 156875425b731c514bf90c985275d80aa7886727d83fChris Dearman#endif 156999e3e6e72e3471eb85fc2e405866392b01c080febuzbee#if defined(WITH_JIT) 157099e3e6e72e3471eb85fc2e405866392b01c080febuzbee if (thread->pJitProfTable != gDvmJit.pProfTable) { 1571062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block ALOGD("Warning: pJitProfTable mismatch - %#x:%#x, tid[%d]", 157299e3e6e72e3471eb85fc2e405866392b01c080febuzbee (int)thread->pJitProfTable,(int)gDvmJit.pProfTable, 157399e3e6e72e3471eb85fc2e405866392b01c080febuzbee thread->threadId); 157499e3e6e72e3471eb85fc2e405866392b01c080febuzbee } 157599e3e6e72e3471eb85fc2e405866392b01c080febuzbee if (thread->jitThreshold != gDvmJit.threshold) { 1576062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block ALOGD("Warning: jitThreshold mismatch - %#x:%#x, tid[%d]", 157799e3e6e72e3471eb85fc2e405866392b01c080febuzbee (int)thread->jitThreshold,(int)gDvmJit.threshold, 157899e3e6e72e3471eb85fc2e405866392b01c080febuzbee thread->threadId); 157999e3e6e72e3471eb85fc2e405866392b01c080febuzbee } 158099e3e6e72e3471eb85fc2e405866392b01c080febuzbee#endif 158199e3e6e72e3471eb85fc2e405866392b01c080febuzbee } 158299e3e6e72e3471eb85fc2e405866392b01c080febuzbee dvmUnlockThreadList(); 158399e3e6e72e3471eb85fc2e405866392b01c080febuzbee} 158499e3e6e72e3471eb85fc2e405866392b01c080febuzbee 158599e3e6e72e3471eb85fc2e405866392b01c080febuzbee/* 158694d65255849ce9f195c971f726e8b09449ba4d14buzbee * Arm a safepoint callback for a thread. If funct is null, 158794d65255849ce9f195c971f726e8b09449ba4d14buzbee * clear any pending callback. 158894d65255849ce9f195c971f726e8b09449ba4d14buzbee * TODO: only gc is currently using this feature, and will have 158994d65255849ce9f195c971f726e8b09449ba4d14buzbee * at most a single outstanding callback request. Until we need 159094d65255849ce9f195c971f726e8b09449ba4d14buzbee * something more capable and flexible, enforce this limit. 159194d65255849ce9f195c971f726e8b09449ba4d14buzbee */ 159294d65255849ce9f195c971f726e8b09449ba4d14buzbeevoid dvmArmSafePointCallback(Thread* thread, SafePointCallback funct, 159394d65255849ce9f195c971f726e8b09449ba4d14buzbee void* arg) 159494d65255849ce9f195c971f726e8b09449ba4d14buzbee{ 159594d65255849ce9f195c971f726e8b09449ba4d14buzbee dvmLockMutex(&thread->callbackMutex); 159694d65255849ce9f195c971f726e8b09449ba4d14buzbee if ((funct == NULL) || (thread->callback == NULL)) { 159794d65255849ce9f195c971f726e8b09449ba4d14buzbee thread->callback = funct; 159894d65255849ce9f195c971f726e8b09449ba4d14buzbee thread->callbackArg = arg; 1599cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee if (funct != NULL) { 1600cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee dvmEnableSubMode(thread, kSubModeCallbackPending); 1601cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee } else { 1602cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee dvmDisableSubMode(thread, kSubModeCallbackPending); 1603cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee } 160494d65255849ce9f195c971f726e8b09449ba4d14buzbee } else { 160594d65255849ce9f195c971f726e8b09449ba4d14buzbee // Already armed. Different? 160694d65255849ce9f195c971f726e8b09449ba4d14buzbee if ((funct != thread->callback) || 160794d65255849ce9f195c971f726e8b09449ba4d14buzbee (arg != thread->callbackArg)) { 160894d65255849ce9f195c971f726e8b09449ba4d14buzbee // Yes - report failure and die 1609c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block ALOGE("ArmSafePointCallback failed, thread %d", thread->threadId); 161094d65255849ce9f195c971f726e8b09449ba4d14buzbee dvmUnlockMutex(&thread->callbackMutex); 161194d65255849ce9f195c971f726e8b09449ba4d14buzbee dvmAbort(); 161294d65255849ce9f195c971f726e8b09449ba4d14buzbee } 161394d65255849ce9f195c971f726e8b09449ba4d14buzbee } 161494d65255849ce9f195c971f726e8b09449ba4d14buzbee dvmUnlockMutex(&thread->callbackMutex); 161594d65255849ce9f195c971f726e8b09449ba4d14buzbee} 161694d65255849ce9f195c971f726e8b09449ba4d14buzbee 161794d65255849ce9f195c971f726e8b09449ba4d14buzbee/* 16189f601a917c8878204482c37aec7005054b6776fabuzbee * One-time initialization at thread creation. Here we initialize 16199f601a917c8878204482c37aec7005054b6776fabuzbee * useful constants. 16202ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */ 16219f601a917c8878204482c37aec7005054b6776fabuzbeevoid dvmInitInterpreterState(Thread* self) 16222ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project{ 1623ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng#if defined(WITH_JIT) 162438329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng /* 1625ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * Reserve a static entity here to quickly setup runtime contents as 1626ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * gcc will issue block copy instructions. 1627ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng */ 1628ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng static struct JitToInterpEntries jitToInterpEntries = { 1629ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmJitToInterpNormal, 1630ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmJitToInterpNoChain, 1631ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmJitToInterpPunt, 1632ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmJitToInterpSingleStep, 163340094c16d9727cc1e047a7d4bddffe04dd566211Ben Cheng dvmJitToInterpTraceSelect, 163497319a8a234e9fe1cf90ca39aa6eca37d729afd5Jeff Hao#if defined(WITH_SELF_VERIFICATION) 163540094c16d9727cc1e047a7d4bddffe04dd566211Ben Cheng dvmJitToInterpBackwardBranch, 16369f601a917c8878204482c37aec7005054b6776fabuzbee#else 16379f601a917c8878204482c37aec7005054b6776fabuzbee NULL, 163897319a8a234e9fe1cf90ca39aa6eca37d729afd5Jeff Hao#endif 1639ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng }; 16409f601a917c8878204482c37aec7005054b6776fabuzbee#endif 16419f601a917c8878204482c37aec7005054b6776fabuzbee 16429f601a917c8878204482c37aec7005054b6776fabuzbee // Begin initialization 16439f601a917c8878204482c37aec7005054b6776fabuzbee self->cardTable = gDvm.biasedCardTableBase; 16449f601a917c8878204482c37aec7005054b6776fabuzbee#if defined(WITH_JIT) 16459a3147c7412f4794434b4c2604aa2ba784867774buzbee // One-time initializations 16469f601a917c8878204482c37aec7005054b6776fabuzbee self->jitToInterpEntries = jitToInterpEntries; 16479f601a917c8878204482c37aec7005054b6776fabuzbee self->icRechainCount = PREDICTED_CHAIN_COUNTER_RECHAIN; 16489f601a917c8878204482c37aec7005054b6776fabuzbee self->pProfileCountdown = &gDvmJit.profileCountdown; 16499a3147c7412f4794434b4c2604aa2ba784867774buzbee // Jit state that can change 165099e3e6e72e3471eb85fc2e405866392b01c080febuzbee dvmJitUpdateThreadStateSingle(self); 16519f601a917c8878204482c37aec7005054b6776fabuzbee#endif 16522ec9f7802034144383261b2fd915bdf1eb396ea4buzbee dvmInitializeInterpBreak(self); 165399e3e6e72e3471eb85fc2e405866392b01c080febuzbee} 16547a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng 165599e3e6e72e3471eb85fc2e405866392b01c080febuzbee/* 165699e3e6e72e3471eb85fc2e405866392b01c080febuzbee * For a newly-created thread, we need to start off with interpBreak 165799e3e6e72e3471eb85fc2e405866392b01c080febuzbee * set to any existing global modes. The caller must hold the 165899e3e6e72e3471eb85fc2e405866392b01c080febuzbee * thread list lock. 165999e3e6e72e3471eb85fc2e405866392b01c080febuzbee */ 166099e3e6e72e3471eb85fc2e405866392b01c080febuzbeevoid dvmInitializeInterpBreak(Thread* thread) 166199e3e6e72e3471eb85fc2e405866392b01c080febuzbee{ 166299e3e6e72e3471eb85fc2e405866392b01c080febuzbee if (gDvm.instructionCountEnableCount > 0) { 1663cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee dvmEnableSubMode(thread, kSubModeInstCounting); 166499e3e6e72e3471eb85fc2e405866392b01c080febuzbee } 166599e3e6e72e3471eb85fc2e405866392b01c080febuzbee if (dvmIsMethodTraceActive()) { 1666cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee dvmEnableSubMode(thread, kSubModeMethodTrace); 1667cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee } 1668cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee if (gDvm.emulatorTraceEnableCount > 0) { 1669cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee dvmEnableSubMode(thread, kSubModeEmulatorTrace); 167099e3e6e72e3471eb85fc2e405866392b01c080febuzbee } 167199e3e6e72e3471eb85fc2e405866392b01c080febuzbee if (gDvm.debuggerActive) { 1672cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee dvmEnableSubMode(thread, kSubModeDebuggerActive); 167399e3e6e72e3471eb85fc2e405866392b01c080febuzbee } 16742ec9f7802034144383261b2fd915bdf1eb396ea4buzbee#if 0 16752ec9f7802034144383261b2fd915bdf1eb396ea4buzbee // Debugging stress mode - force checkBefore 16762ec9f7802034144383261b2fd915bdf1eb396ea4buzbee dvmEnableSubMode(thread, kSubModeCheckAlways); 16772ec9f7802034144383261b2fd915bdf1eb396ea4buzbee#endif 16789f601a917c8878204482c37aec7005054b6776fabuzbee} 16799f601a917c8878204482c37aec7005054b6776fabuzbee 1680a7d59bbafea5430fe81fc21ba94ddf6f6a63b0b3buzbee/* 1681a7d59bbafea5430fe81fc21ba94ddf6f6a63b0b3buzbee * Inter-instruction handler invoked in between instruction interpretations 1682a7d59bbafea5430fe81fc21ba94ddf6f6a63b0b3buzbee * to handle exceptional events such as debugging housekeeping, instruction 16839a3147c7412f4794434b4c2604aa2ba784867774buzbee * count profiling, JIT trace building, etc. Dalvik PC has been exported 16849a3147c7412f4794434b4c2604aa2ba784867774buzbee * prior to call, but Thread copy of dPC & fp are not current. 1685a7d59bbafea5430fe81fc21ba94ddf6f6a63b0b3buzbee */ 168694d65255849ce9f195c971f726e8b09449ba4d14buzbeevoid dvmCheckBefore(const u2 *pc, u4 *fp, Thread* self) 1687a7d59bbafea5430fe81fc21ba94ddf6f6a63b0b3buzbee{ 16889a3147c7412f4794434b4c2604aa2ba784867774buzbee const Method* method = self->interpSave.method; 16899a3147c7412f4794434b4c2604aa2ba784867774buzbee assert(pc >= method->insns && pc < 16909a3147c7412f4794434b4c2604aa2ba784867774buzbee method->insns + dvmGetMethodInsnsSize(method)); 16919a3147c7412f4794434b4c2604aa2ba784867774buzbee 16929a3147c7412f4794434b4c2604aa2ba784867774buzbee#if 0 16939a3147c7412f4794434b4c2604aa2ba784867774buzbee /* 16949a3147c7412f4794434b4c2604aa2ba784867774buzbee * When we hit a specific method, enable verbose instruction logging. 16959a3147c7412f4794434b4c2604aa2ba784867774buzbee * Sometimes it's helpful to use the debugger attach as a trigger too. 16969a3147c7412f4794434b4c2604aa2ba784867774buzbee */ 16979a3147c7412f4794434b4c2604aa2ba784867774buzbee if (*pIsMethodEntry) { 16989a3147c7412f4794434b4c2604aa2ba784867774buzbee static const char* cd = "Landroid/test/Arithmetic;"; 16999a3147c7412f4794434b4c2604aa2ba784867774buzbee static const char* mn = "shiftTest2"; 17009a3147c7412f4794434b4c2604aa2ba784867774buzbee static const char* sg = "()V"; 17019a3147c7412f4794434b4c2604aa2ba784867774buzbee 17029a3147c7412f4794434b4c2604aa2ba784867774buzbee if (/*self->interpBreak.ctl.subMode & kSubModeDebuggerActive &&*/ 17039a3147c7412f4794434b4c2604aa2ba784867774buzbee strcmp(method->clazz->descriptor, cd) == 0 && 17049a3147c7412f4794434b4c2604aa2ba784867774buzbee strcmp(method->name, mn) == 0 && 17059a3147c7412f4794434b4c2604aa2ba784867774buzbee strcmp(method->shorty, sg) == 0) 17069a3147c7412f4794434b4c2604aa2ba784867774buzbee { 1707e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block ALOGW("Reached %s.%s, enabling verbose mode", 17089a3147c7412f4794434b4c2604aa2ba784867774buzbee method->clazz->descriptor, method->name); 17099a3147c7412f4794434b4c2604aa2ba784867774buzbee android_setMinPriority(LOG_TAG"i", ANDROID_LOG_VERBOSE); 17109a3147c7412f4794434b4c2604aa2ba784867774buzbee dumpRegs(method, fp, true); 17119a3147c7412f4794434b4c2604aa2ba784867774buzbee } 17129a3147c7412f4794434b4c2604aa2ba784867774buzbee 17139a3147c7412f4794434b4c2604aa2ba784867774buzbee if (!gDvm.debuggerActive) 17149a3147c7412f4794434b4c2604aa2ba784867774buzbee *pIsMethodEntry = false; 17159a3147c7412f4794434b4c2604aa2ba784867774buzbee } 17169a3147c7412f4794434b4c2604aa2ba784867774buzbee#endif 17179a3147c7412f4794434b4c2604aa2ba784867774buzbee 171894d65255849ce9f195c971f726e8b09449ba4d14buzbee /* Safe point handling */ 1719389e258a5b9b2afb7bfaee3344c615d3310fae4ebuzbee if (self->suspendCount || 1720cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee (self->interpBreak.ctl.subMode & kSubModeCallbackPending)) { 1721c4a8cafcd62484c1006c5dc9978731a5b7ce403dbuzbee // Are we are a safe point? 1722c4a8cafcd62484c1006c5dc9978731a5b7ce403dbuzbee int flags; 1723c4a8cafcd62484c1006c5dc9978731a5b7ce403dbuzbee flags = dexGetFlagsFromOpcode(dexOpcodeFromCodeUnit(*pc)); 17246e0be609807de9fabe1b63a75f7c7d619bfa2f9fJesse Wilson if (flags & (VERIFY_GC_INST_MASK & ~kInstrCanThrow)) { 172594d65255849ce9f195c971f726e8b09449ba4d14buzbee // Yes, at a safe point. Pending callback? 1726cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee if (self->interpBreak.ctl.subMode & kSubModeCallbackPending) { 172794d65255849ce9f195c971f726e8b09449ba4d14buzbee SafePointCallback callback; 172894d65255849ce9f195c971f726e8b09449ba4d14buzbee void* arg; 172994d65255849ce9f195c971f726e8b09449ba4d14buzbee // Get consistent funct/arg pair 173094d65255849ce9f195c971f726e8b09449ba4d14buzbee dvmLockMutex(&self->callbackMutex); 173194d65255849ce9f195c971f726e8b09449ba4d14buzbee callback = self->callback; 173294d65255849ce9f195c971f726e8b09449ba4d14buzbee arg = self->callbackArg; 173394d65255849ce9f195c971f726e8b09449ba4d14buzbee dvmUnlockMutex(&self->callbackMutex); 173494d65255849ce9f195c971f726e8b09449ba4d14buzbee // Update Thread structure 173594d65255849ce9f195c971f726e8b09449ba4d14buzbee self->interpSave.pc = pc; 173630bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee self->interpSave.curFrame = fp; 173794d65255849ce9f195c971f726e8b09449ba4d14buzbee if (callback != NULL) { 173894d65255849ce9f195c971f726e8b09449ba4d14buzbee // Do the callback 173994d65255849ce9f195c971f726e8b09449ba4d14buzbee if (!callback(self,arg)) { 174094d65255849ce9f195c971f726e8b09449ba4d14buzbee // disarm 174194d65255849ce9f195c971f726e8b09449ba4d14buzbee dvmArmSafePointCallback(self, NULL, NULL); 174294d65255849ce9f195c971f726e8b09449ba4d14buzbee } 174394d65255849ce9f195c971f726e8b09449ba4d14buzbee } 174494d65255849ce9f195c971f726e8b09449ba4d14buzbee } 174594d65255849ce9f195c971f726e8b09449ba4d14buzbee // Need to suspend? 1746389e258a5b9b2afb7bfaee3344c615d3310fae4ebuzbee if (self->suspendCount) { 174794d65255849ce9f195c971f726e8b09449ba4d14buzbee dvmExportPC(pc, fp); 174894d65255849ce9f195c971f726e8b09449ba4d14buzbee dvmCheckSuspendPending(self); 174994d65255849ce9f195c971f726e8b09449ba4d14buzbee } 1750c4a8cafcd62484c1006c5dc9978731a5b7ce403dbuzbee } 17519a3147c7412f4794434b4c2604aa2ba784867774buzbee } 17529a3147c7412f4794434b4c2604aa2ba784867774buzbee 17539a3147c7412f4794434b4c2604aa2ba784867774buzbee if (self->interpBreak.ctl.subMode & kSubModeDebuggerActive) { 1754e71474621b968a9bc649d067155d31213f5764a9buzbee updateDebugger(method, pc, fp, self); 17559a3147c7412f4794434b4c2604aa2ba784867774buzbee } 17569a3147c7412f4794434b4c2604aa2ba784867774buzbee if (gDvm.instructionCountEnableCount != 0) { 17579a3147c7412f4794434b4c2604aa2ba784867774buzbee /* 17589a3147c7412f4794434b4c2604aa2ba784867774buzbee * Count up the #of executed instructions. This isn't synchronized 17599a3147c7412f4794434b4c2604aa2ba784867774buzbee * for thread-safety; if we need that we should make this 17609a3147c7412f4794434b4c2604aa2ba784867774buzbee * thread-local and merge counts into the global area when threads 17619a3147c7412f4794434b4c2604aa2ba784867774buzbee * exit (perhaps suspending all other threads GC-style and pulling 17629a3147c7412f4794434b4c2604aa2ba784867774buzbee * the data out of them). 17639a3147c7412f4794434b4c2604aa2ba784867774buzbee */ 17649a3147c7412f4794434b4c2604aa2ba784867774buzbee gDvm.executedInstrCounts[GET_OPCODE(*pc)]++; 17659a3147c7412f4794434b4c2604aa2ba784867774buzbee } 17669a3147c7412f4794434b4c2604aa2ba784867774buzbee 17679a3147c7412f4794434b4c2604aa2ba784867774buzbee 17689a3147c7412f4794434b4c2604aa2ba784867774buzbee#if defined(WITH_TRACKREF_CHECKS) 17699a3147c7412f4794434b4c2604aa2ba784867774buzbee dvmInterpCheckTrackedRefs(self, method, 17709a3147c7412f4794434b4c2604aa2ba784867774buzbee self->interpSave.debugTrackedRefStart); 17719a3147c7412f4794434b4c2604aa2ba784867774buzbee#endif 17729a3147c7412f4794434b4c2604aa2ba784867774buzbee 17739a3147c7412f4794434b4c2604aa2ba784867774buzbee#if defined(WITH_JIT) 17749a3147c7412f4794434b4c2604aa2ba784867774buzbee // Does the JIT need anything done now? 1775cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee if (self->interpBreak.ctl.subMode & 1776cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee (kSubModeJitTraceBuild | kSubModeJitSV)) { 17779a3147c7412f4794434b4c2604aa2ba784867774buzbee // Are we building a trace? 17789a3147c7412f4794434b4c2604aa2ba784867774buzbee if (self->interpBreak.ctl.subMode & kSubModeJitTraceBuild) { 17799a3147c7412f4794434b4c2604aa2ba784867774buzbee dvmCheckJit(pc, self); 17809a3147c7412f4794434b4c2604aa2ba784867774buzbee } 17819a3147c7412f4794434b4c2604aa2ba784867774buzbee 17829a3147c7412f4794434b4c2604aa2ba784867774buzbee#if defined(WITH_SELF_VERIFICATION) 17839a3147c7412f4794434b4c2604aa2ba784867774buzbee // Are we replaying a trace? 17849a3147c7412f4794434b4c2604aa2ba784867774buzbee if (self->interpBreak.ctl.subMode & kSubModeJitSV) { 17859a3147c7412f4794434b4c2604aa2ba784867774buzbee dvmCheckSelfVerification(pc, self); 17869a3147c7412f4794434b4c2604aa2ba784867774buzbee } 17879a3147c7412f4794434b4c2604aa2ba784867774buzbee#endif 17889a3147c7412f4794434b4c2604aa2ba784867774buzbee } 17899a3147c7412f4794434b4c2604aa2ba784867774buzbee#endif 17909a3147c7412f4794434b4c2604aa2ba784867774buzbee 17919a3147c7412f4794434b4c2604aa2ba784867774buzbee /* 1792313d430d5b3b96b45370ccddee52a6d88a799f35Ben Cheng * CountedStep processing. NOTE: must be the last here to allow 17939a3147c7412f4794434b4c2604aa2ba784867774buzbee * preceeding special case handler to manipulate single-step count. 17949a3147c7412f4794434b4c2604aa2ba784867774buzbee */ 1795313d430d5b3b96b45370ccddee52a6d88a799f35Ben Cheng if (self->interpBreak.ctl.subMode & kSubModeCountedStep) { 17969a3147c7412f4794434b4c2604aa2ba784867774buzbee if (self->singleStepCount == 0) { 17979a3147c7412f4794434b4c2604aa2ba784867774buzbee // We've exhausted our single step count 1798cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee dvmDisableSubMode(self, kSubModeCountedStep); 17999a3147c7412f4794434b4c2604aa2ba784867774buzbee#if defined(WITH_JIT) 18009a3147c7412f4794434b4c2604aa2ba784867774buzbee#if 0 18019a3147c7412f4794434b4c2604aa2ba784867774buzbee /* 18029a3147c7412f4794434b4c2604aa2ba784867774buzbee * For debugging. If jitResumeDPC is non-zero, then 18039a3147c7412f4794434b4c2604aa2ba784867774buzbee * we expect to return to a trace in progress. There 18049a3147c7412f4794434b4c2604aa2ba784867774buzbee * are valid reasons why we wouldn't (such as an exception 18059a3147c7412f4794434b4c2604aa2ba784867774buzbee * throw), but here we can keep track. 18069a3147c7412f4794434b4c2604aa2ba784867774buzbee */ 18079a3147c7412f4794434b4c2604aa2ba784867774buzbee if (self->jitResumeDPC != NULL) { 18089a3147c7412f4794434b4c2604aa2ba784867774buzbee if (self->jitResumeDPC == pc) { 18099a3147c7412f4794434b4c2604aa2ba784867774buzbee if (self->jitResumeNPC != NULL) { 1810062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block ALOGD("SS return to trace - pc:%#x to 0x:%x", 18119a3147c7412f4794434b4c2604aa2ba784867774buzbee (int)pc, (int)self->jitResumeNPC); 18129a3147c7412f4794434b4c2604aa2ba784867774buzbee } else { 1813062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block ALOGD("SS return to interp - pc:%#x",(int)pc); 18149a3147c7412f4794434b4c2604aa2ba784867774buzbee } 18159a3147c7412f4794434b4c2604aa2ba784867774buzbee } else { 1816062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block ALOGD("SS failed to return. Expected %#x, now at %#x", 18179a3147c7412f4794434b4c2604aa2ba784867774buzbee (int)self->jitResumeDPC, (int)pc); 18189a3147c7412f4794434b4c2604aa2ba784867774buzbee } 18199a3147c7412f4794434b4c2604aa2ba784867774buzbee } 18209a3147c7412f4794434b4c2604aa2ba784867774buzbee#endif 1821e3d9cde40f96bf40dd4ad3d495949869bde5dd1eBen Cheng#if 0 1822e3d9cde40f96bf40dd4ad3d495949869bde5dd1eBen Cheng // TODO - fix JIT single-stepping resume mode (b/5551114) 1823e3d9cde40f96bf40dd4ad3d495949869bde5dd1eBen Cheng // self->jitResumeNPC needs to be cleared in callPrep 1824e3d9cde40f96bf40dd4ad3d495949869bde5dd1eBen Cheng 18259a3147c7412f4794434b4c2604aa2ba784867774buzbee // If we've got a native return and no other reasons to 18269a3147c7412f4794434b4c2604aa2ba784867774buzbee // remain in singlestep/break mode, do a long jump 18279a3147c7412f4794434b4c2604aa2ba784867774buzbee if (self->jitResumeNPC != NULL && 18289a3147c7412f4794434b4c2604aa2ba784867774buzbee self->interpBreak.ctl.breakFlags == 0) { 18299a3147c7412f4794434b4c2604aa2ba784867774buzbee assert(self->jitResumeDPC == pc); 18309a3147c7412f4794434b4c2604aa2ba784867774buzbee self->jitResumeDPC = NULL; 18319a3147c7412f4794434b4c2604aa2ba784867774buzbee dvmJitResumeTranslation(self, pc, fp); 18329a3147c7412f4794434b4c2604aa2ba784867774buzbee // Doesn't return 18339a3147c7412f4794434b4c2604aa2ba784867774buzbee dvmAbort(); 18349a3147c7412f4794434b4c2604aa2ba784867774buzbee } 18350c0624bfad83503547b0226bd2dfac055782582aBen Cheng // In case resume is blocked by non-zero breakFlags, clear 18360c0624bfad83503547b0226bd2dfac055782582aBen Cheng // jitResumeNPC here. 18370c0624bfad83503547b0226bd2dfac055782582aBen Cheng self->jitResumeNPC = NULL; 18389a3147c7412f4794434b4c2604aa2ba784867774buzbee self->jitResumeDPC = NULL; 18397209bdd8ded13e5ea1b936c8836a9a798ccfa688buzbee self->inJitCodeCache = NULL; 18409a3147c7412f4794434b4c2604aa2ba784867774buzbee#endif 1841e3d9cde40f96bf40dd4ad3d495949869bde5dd1eBen Cheng#endif 18429a3147c7412f4794434b4c2604aa2ba784867774buzbee } else { 18439a3147c7412f4794434b4c2604aa2ba784867774buzbee self->singleStepCount--; 18449a3147c7412f4794434b4c2604aa2ba784867774buzbee#if defined(WITH_JIT) 18459a3147c7412f4794434b4c2604aa2ba784867774buzbee if ((self->singleStepCount > 0) && (self->jitResumeNPC != NULL)) { 18469a3147c7412f4794434b4c2604aa2ba784867774buzbee /* 18479a3147c7412f4794434b4c2604aa2ba784867774buzbee * Direct return to an existing translation following a 18489a3147c7412f4794434b4c2604aa2ba784867774buzbee * single step is valid only if we step once. If we're 18499a3147c7412f4794434b4c2604aa2ba784867774buzbee * here, an additional step was added so we need to invalidate 18509a3147c7412f4794434b4c2604aa2ba784867774buzbee * the return to translation. 18519a3147c7412f4794434b4c2604aa2ba784867774buzbee */ 18529a3147c7412f4794434b4c2604aa2ba784867774buzbee self->jitResumeNPC = NULL; 18537209bdd8ded13e5ea1b936c8836a9a798ccfa688buzbee self->inJitCodeCache = NULL; 18549a3147c7412f4794434b4c2604aa2ba784867774buzbee } 18559a3147c7412f4794434b4c2604aa2ba784867774buzbee#endif 18569a3147c7412f4794434b4c2604aa2ba784867774buzbee } 18579a3147c7412f4794434b4c2604aa2ba784867774buzbee } 1858a7d59bbafea5430fe81fc21ba94ddf6f6a63b0b3buzbee} 18599f601a917c8878204482c37aec7005054b6776fabuzbee 18609f601a917c8878204482c37aec7005054b6776fabuzbee/* 18619a3147c7412f4794434b4c2604aa2ba784867774buzbee * Main interpreter loop entry point. 18629f601a917c8878204482c37aec7005054b6776fabuzbee * 18639f601a917c8878204482c37aec7005054b6776fabuzbee * This begins executing code at the start of "method". On exit, "pResult" 18649f601a917c8878204482c37aec7005054b6776fabuzbee * holds the return value of the method (or, if "method" returns NULL, it 18659f601a917c8878204482c37aec7005054b6776fabuzbee * holds an undefined value). 18669f601a917c8878204482c37aec7005054b6776fabuzbee * 18679f601a917c8878204482c37aec7005054b6776fabuzbee * The interpreted stack frame, which holds the method arguments, has 18689f601a917c8878204482c37aec7005054b6776fabuzbee * already been set up. 18699f601a917c8878204482c37aec7005054b6776fabuzbee */ 18709f601a917c8878204482c37aec7005054b6776fabuzbeevoid dvmInterpret(Thread* self, const Method* method, JValue* pResult) 18719f601a917c8878204482c37aec7005054b6776fabuzbee{ 18729f601a917c8878204482c37aec7005054b6776fabuzbee InterpSaveState interpSaveState; 1873cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee ExecutionSubModes savedSubModes; 18749a3147c7412f4794434b4c2604aa2ba784867774buzbee 18759f601a917c8878204482c37aec7005054b6776fabuzbee#if defined(WITH_JIT) 18769f601a917c8878204482c37aec7005054b6776fabuzbee /* Target-specific save/restore */ 18779f601a917c8878204482c37aec7005054b6776fabuzbee double calleeSave[JIT_CALLEE_SAVE_DOUBLE_COUNT]; 18787a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng /* 18797a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng * If the previous VM left the code cache through single-stepping the 18807a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng * inJitCodeCache flag will be set when the VM is re-entered (for example, 18817a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng * in self-verification mode we single-step NEW_INSTANCE which may re-enter 18827a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng * the VM through findClassFromLoaderNoInit). Because of that, we cannot 18837a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng * assert that self->inJitCodeCache is NULL here. 18847a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng */ 1885ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng#endif 1886ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 18879f601a917c8878204482c37aec7005054b6776fabuzbee /* 18889f601a917c8878204482c37aec7005054b6776fabuzbee * Save interpreter state from previous activation, linking 18899f601a917c8878204482c37aec7005054b6776fabuzbee * new to last. 18909f601a917c8878204482c37aec7005054b6776fabuzbee */ 18919f601a917c8878204482c37aec7005054b6776fabuzbee interpSaveState = self->interpSave; 18929f601a917c8878204482c37aec7005054b6776fabuzbee self->interpSave.prev = &interpSaveState; 18939a3147c7412f4794434b4c2604aa2ba784867774buzbee /* 18949a3147c7412f4794434b4c2604aa2ba784867774buzbee * Strip out and save any flags that should not be inherited by 18959a3147c7412f4794434b4c2604aa2ba784867774buzbee * nested interpreter activation. 18969a3147c7412f4794434b4c2604aa2ba784867774buzbee */ 1897cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee savedSubModes = (ExecutionSubModes)( 1898cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee self->interpBreak.ctl.subMode & LOCAL_SUBMODE); 1899cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee if (savedSubModes != kSubModeNormal) { 1900cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee dvmDisableSubMode(self, savedSubModes); 19019a3147c7412f4794434b4c2604aa2ba784867774buzbee } 19029f601a917c8878204482c37aec7005054b6776fabuzbee#if defined(WITH_JIT) 19039f601a917c8878204482c37aec7005054b6776fabuzbee dvmJitCalleeSave(calleeSave); 19049f601a917c8878204482c37aec7005054b6776fabuzbee#endif 19059f601a917c8878204482c37aec7005054b6776fabuzbee 19062ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project 19072ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#if defined(WITH_TRACKREF_CHECKS) 1908ef5db621255680dbbe46cfcce572989deea64387buzbee self->interpSave.debugTrackedRefStart = 19092ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project dvmReferenceTableEntries(&self->internalLocalRefTable); 19102ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project#endif 19119f601a917c8878204482c37aec7005054b6776fabuzbee self->debugIsMethodEntry = true; 1912ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng#if defined(WITH_JIT) 19139f601a917c8878204482c37aec7005054b6776fabuzbee dvmJitCalleeSave(calleeSave); 1914a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng /* Initialize the state to kJitNot */ 19159f601a917c8878204482c37aec7005054b6776fabuzbee self->jitState = kJitNot; 1916ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng#endif 19172ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project 19182ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project /* 19192ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Initialize working state. 19202ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * 19212ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * No need to initialize "retval". 19222ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */ 19239f601a917c8878204482c37aec7005054b6776fabuzbee self->interpSave.method = method; 192430bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee self->interpSave.curFrame = (u4*) self->interpSave.curFrame; 19259f601a917c8878204482c37aec7005054b6776fabuzbee self->interpSave.pc = method->insns; 19262ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project 19272ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project assert(!dvmIsNativeMethod(method)); 19282ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project 19292ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project /* 19302ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * Make sure the class is ready to go. Shouldn't be possible to get 19312ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project * here otherwise. 19322ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project */ 19332ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project if (method->clazz->status < CLASS_INITIALIZING || 19342ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project method->clazz->status == CLASS_ERROR) 19352ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project { 1936c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block ALOGE("ERROR: tried to execute code in unprepared class '%s' (%d)", 19372ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project method->clazz->descriptor, method->clazz->status); 19382ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project dvmDumpThread(self, false); 19392ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project dvmAbort(); 19402ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project } 19412ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project 19429a3147c7412f4794434b4c2604aa2ba784867774buzbee typedef void (*Interpreter)(Thread*); 19432ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project Interpreter stdInterp; 19442ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project if (gDvm.executionMode == kExecutionModeInterpFast) 19452ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project stdInterp = dvmMterpStd; 1946ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng#if defined(WITH_JIT) 19470c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen else if (gDvm.executionMode == kExecutionModeJit || 19480c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen gDvm.executionMode == kExecutionModeNcgO0 || 19490c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen gDvm.executionMode == kExecutionModeNcgO1) 1950ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng stdInterp = dvmMterpStd; 1951ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng#endif 19522ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project else 19539a3147c7412f4794434b4c2604aa2ba784867774buzbee stdInterp = dvmInterpretPortable; 19549a3147c7412f4794434b4c2604aa2ba784867774buzbee 19559a3147c7412f4794434b4c2604aa2ba784867774buzbee // Call the interpreter 19569a3147c7412f4794434b4c2604aa2ba784867774buzbee (*stdInterp)(self); 19572ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project 1958cf4a20cf0cbc53f03a5b16c7152bbb29907f7108buzbee *pResult = self->interpSave.retval; 19599f601a917c8878204482c37aec7005054b6776fabuzbee 19609f601a917c8878204482c37aec7005054b6776fabuzbee /* Restore interpreter state from previous activation */ 19619f601a917c8878204482c37aec7005054b6776fabuzbee self->interpSave = interpSaveState; 1962342806dae77556290dfe0760e6fe3117d812c7baBill Buzbee#if defined(WITH_JIT) 19639f601a917c8878204482c37aec7005054b6776fabuzbee dvmJitCalleeRestore(calleeSave); 1964342806dae77556290dfe0760e6fe3117d812c7baBill Buzbee#endif 1965cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee if (savedSubModes != kSubModeNormal) { 1966cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee dvmEnableSubMode(self, savedSubModes); 19679a3147c7412f4794434b4c2604aa2ba784867774buzbee } 19682ad60cfc28e14ee8f0bb038720836a4696c478aThe Android Open Source Project} 1969