blob: 092df320744e43f56ec48ee8b16d5620ad4b8308 [file] [log] [blame]
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
The Android Open Source Project89c1feb2008-12-17 18:03:55 -080016
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -070017/*
18 * Main interpreter entry point and support functions.
19 *
20 * The entry point selects the "standard" or "debug" interpreter and
21 * facilitates switching between them. The standard interpreter may
22 * use the "fast" or "portable" implementation.
23 *
Andy McFadden0d615c32010-08-18 12:19:51 -070024 * Some debugger support functions are included here.
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -070025 */
26#include "Dalvik.h"
27#include "interp/InterpDefs.h"
buzbee9a3147c2011-03-02 15:43:48 -080028#if defined(WITH_JIT)
29#include "interp/Jit.h"
30#endif
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -070031
32
33/*
34 * ===========================================================================
35 * Debugger support
36 * ===========================================================================
37 */
38
Andy McFadden96516932009-10-28 17:39:02 -070039// fwd
40static BreakpointSet* dvmBreakpointSetAlloc(void);
41static void dvmBreakpointSetFree(BreakpointSet* pSet);
42
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -070043/*
Andy McFadden96516932009-10-28 17:39:02 -070044 * Initialize global breakpoint structures.
45 */
46bool dvmBreakpointStartup(void)
47{
Andy McFadden96516932009-10-28 17:39:02 -070048 gDvm.breakpointSet = dvmBreakpointSetAlloc();
49 return (gDvm.breakpointSet != NULL);
Andy McFadden96516932009-10-28 17:39:02 -070050}
51
52/*
53 * Free resources.
54 */
55void dvmBreakpointShutdown(void)
56{
Andy McFadden96516932009-10-28 17:39:02 -070057 dvmBreakpointSetFree(gDvm.breakpointSet);
Andy McFadden96516932009-10-28 17:39:02 -070058}
59
60
Andy McFadden96516932009-10-28 17:39:02 -070061/*
62 * This represents a breakpoint inserted in the instruction stream.
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -070063 *
Andy McFadden96516932009-10-28 17:39:02 -070064 * The debugger may ask us to create the same breakpoint multiple times.
65 * We only remove the breakpoint when the last instance is cleared.
66 */
67typedef struct {
Andy McFaddend22748a2010-04-22 17:08:11 -070068 Method* method; /* method we're associated with */
Andy McFadden96516932009-10-28 17:39:02 -070069 u2* addr; /* absolute memory address */
Dan Bornstein9a1f8162010-12-01 17:02:26 -080070 u1 originalOpcode; /* original 8-bit opcode value */
Andy McFadden96516932009-10-28 17:39:02 -070071 int setCount; /* #of times this breakpoint was set */
72} Breakpoint;
73
74/*
75 * Set of breakpoints.
76 */
77struct BreakpointSet {
78 /* grab lock before reading or writing anything else in here */
79 pthread_mutex_t lock;
80
81 /* vector of breakpoint structures */
82 int alloc;
83 int count;
84 Breakpoint* breakpoints;
85};
86
87/*
88 * Initialize a BreakpointSet. Initially empty.
89 */
90static BreakpointSet* dvmBreakpointSetAlloc(void)
91{
92 BreakpointSet* pSet = (BreakpointSet*) calloc(1, sizeof(*pSet));
93
94 dvmInitMutex(&pSet->lock);
95 /* leave the rest zeroed -- will alloc on first use */
96
97 return pSet;
98}
99
100/*
101 * Free storage associated with a BreakpointSet.
102 */
103static void dvmBreakpointSetFree(BreakpointSet* pSet)
104{
105 if (pSet == NULL)
106 return;
107
108 free(pSet->breakpoints);
109 free(pSet);
110}
111
112/*
113 * Lock the breakpoint set.
Andy McFaddend22748a2010-04-22 17:08:11 -0700114 *
115 * It's not currently necessary to switch to VMWAIT in the event of
116 * contention, because nothing in here can block. However, it's possible
117 * that the bytecode-updater code could become fancier in the future, so
118 * we do the trylock dance as a bit of future-proofing.
Andy McFadden96516932009-10-28 17:39:02 -0700119 */
120static void dvmBreakpointSetLock(BreakpointSet* pSet)
121{
Andy McFaddend22748a2010-04-22 17:08:11 -0700122 if (dvmTryLockMutex(&pSet->lock) != 0) {
123 Thread* self = dvmThreadSelf();
Carl Shapiro5617ad32010-07-02 10:50:57 -0700124 ThreadStatus oldStatus = dvmChangeStatus(self, THREAD_VMWAIT);
Andy McFaddend22748a2010-04-22 17:08:11 -0700125 dvmLockMutex(&pSet->lock);
126 dvmChangeStatus(self, oldStatus);
127 }
Andy McFadden96516932009-10-28 17:39:02 -0700128}
129
130/*
131 * Unlock the breakpoint set.
132 */
133static void dvmBreakpointSetUnlock(BreakpointSet* pSet)
134{
135 dvmUnlockMutex(&pSet->lock);
136}
137
138/*
139 * Return the #of breakpoints.
140 */
141static int dvmBreakpointSetCount(const BreakpointSet* pSet)
142{
143 return pSet->count;
144}
145
146/*
147 * See if we already have an entry for this address.
148 *
149 * The BreakpointSet's lock must be acquired before calling here.
150 *
151 * Returns the index of the breakpoint entry, or -1 if not found.
152 */
153static int dvmBreakpointSetFind(const BreakpointSet* pSet, const u2* addr)
154{
155 int i;
156
157 for (i = 0; i < pSet->count; i++) {
158 Breakpoint* pBreak = &pSet->breakpoints[i];
159 if (pBreak->addr == addr)
160 return i;
161 }
162
163 return -1;
164}
165
166/*
167 * Retrieve the opcode that was originally at the specified location.
168 *
169 * The BreakpointSet's lock must be acquired before calling here.
170 *
171 * Returns "true" with the opcode in *pOrig on success.
172 */
Dan Bornstein9a1f8162010-12-01 17:02:26 -0800173static bool dvmBreakpointSetOriginalOpcode(const BreakpointSet* pSet,
Andy McFadden96516932009-10-28 17:39:02 -0700174 const u2* addr, u1* pOrig)
175{
176 int idx = dvmBreakpointSetFind(pSet, addr);
177 if (idx < 0)
178 return false;
179
Dan Bornstein9a1f8162010-12-01 17:02:26 -0800180 *pOrig = pSet->breakpoints[idx].originalOpcode;
Andy McFadden96516932009-10-28 17:39:02 -0700181 return true;
182}
183
184/*
Andy McFaddenda9dc842010-05-03 16:11:20 -0700185 * Check the opcode. If it's a "magic" NOP, indicating the start of
186 * switch or array data in the instruction stream, we don't want to set
187 * a breakpoint.
188 *
189 * This can happen because the line number information dx generates
190 * associates the switch data with the switch statement's line number,
191 * and some debuggers put breakpoints at every address associated with
192 * a given line. The result is that the breakpoint stomps on the NOP
193 * instruction that doubles as a data table magic number, and an explicit
194 * check in the interpreter results in an exception being thrown.
195 *
196 * We don't want to simply refuse to add the breakpoint to the table,
197 * because that confuses the housekeeping. We don't want to reject the
198 * debugger's event request, and we want to be sure that there's exactly
199 * one un-set operation for every set op.
200 */
201static bool instructionIsMagicNop(const u2* addr)
202{
203 u2 curVal = *addr;
buzbee9a3147c2011-03-02 15:43:48 -0800204 return ((GET_OPCODE(curVal)) == OP_NOP && (curVal >> 8) != 0);
Andy McFaddenda9dc842010-05-03 16:11:20 -0700205}
206
207/*
Andy McFadden96516932009-10-28 17:39:02 -0700208 * Add a breakpoint at a specific address. If the address is already
209 * present in the table, this just increments the count.
210 *
211 * For a new entry, this will extract and preserve the current opcode from
212 * the instruction stream, and replace it with a breakpoint opcode.
213 *
214 * The BreakpointSet's lock must be acquired before calling here.
215 *
216 * Returns "true" on success.
217 */
218static bool dvmBreakpointSetAdd(BreakpointSet* pSet, Method* method,
219 unsigned int instrOffset)
220{
221 const int kBreakpointGrowth = 10;
222 const u2* addr = method->insns + instrOffset;
223 int idx = dvmBreakpointSetFind(pSet, addr);
224 Breakpoint* pBreak;
225
226 if (idx < 0) {
227 if (pSet->count == pSet->alloc) {
228 int newSize = pSet->alloc + kBreakpointGrowth;
229 Breakpoint* newVec;
230
231 LOGV("+++ increasing breakpoint set size to %d\n", newSize);
232
233 /* pSet->breakpoints will be NULL on first entry */
Carl Shapirofc75f3e2010-12-07 11:43:38 -0800234 newVec = (Breakpoint*)realloc(pSet->breakpoints, newSize * sizeof(Breakpoint));
Andy McFadden96516932009-10-28 17:39:02 -0700235 if (newVec == NULL)
236 return false;
237
238 pSet->breakpoints = newVec;
239 pSet->alloc = newSize;
240 }
241
242 pBreak = &pSet->breakpoints[pSet->count++];
Andy McFaddend22748a2010-04-22 17:08:11 -0700243 pBreak->method = method;
Andy McFadden96516932009-10-28 17:39:02 -0700244 pBreak->addr = (u2*)addr;
Dan Bornstein9a1f8162010-12-01 17:02:26 -0800245 pBreak->originalOpcode = *(u1*)addr;
Andy McFadden96516932009-10-28 17:39:02 -0700246 pBreak->setCount = 1;
247
248 /*
249 * Change the opcode. We must ensure that the BreakpointSet
250 * updates happen before we change the opcode.
Andy McFaddend22748a2010-04-22 17:08:11 -0700251 *
252 * If the method has not been verified, we do NOT insert the
253 * breakpoint yet, since that will screw up the verifier. The
254 * debugger is allowed to insert breakpoints in unverified code,
255 * but since we don't execute unverified code we don't need to
256 * alter the bytecode yet.
257 *
Andy McFaddenc7a12b22010-04-30 10:08:55 -0700258 * The class init code will "flush" all pending opcode writes
259 * before verification completes.
Andy McFadden96516932009-10-28 17:39:02 -0700260 */
Andy McFadden96516932009-10-28 17:39:02 -0700261 assert(*(u1*)addr != OP_BREAKPOINT);
Andy McFaddend22748a2010-04-22 17:08:11 -0700262 if (dvmIsClassVerified(method->clazz)) {
263 LOGV("Class %s verified, adding breakpoint at %p\n",
264 method->clazz->descriptor, addr);
Andy McFaddenda9dc842010-05-03 16:11:20 -0700265 if (instructionIsMagicNop(addr)) {
266 LOGV("Refusing to set breakpoint on %04x at %s.%s + 0x%x\n",
267 *addr, method->clazz->descriptor, method->name,
268 instrOffset);
269 } else {
Andy McFadden6e10b9a2010-06-14 15:24:39 -0700270 ANDROID_MEMBAR_FULL();
Andy McFaddenda9dc842010-05-03 16:11:20 -0700271 dvmDexChangeDex1(method->clazz->pDvmDex, (u1*)addr,
272 OP_BREAKPOINT);
273 }
Andy McFaddend22748a2010-04-22 17:08:11 -0700274 } else {
275 LOGV("Class %s NOT verified, deferring breakpoint at %p\n",
276 method->clazz->descriptor, addr);
277 }
Andy McFadden96516932009-10-28 17:39:02 -0700278 } else {
Andy McFaddenc7a12b22010-04-30 10:08:55 -0700279 /*
280 * Breakpoint already exists, just increase the count.
281 */
Andy McFadden96516932009-10-28 17:39:02 -0700282 pBreak = &pSet->breakpoints[idx];
283 pBreak->setCount++;
Andy McFadden96516932009-10-28 17:39:02 -0700284 }
285
286 return true;
287}
288
289/*
290 * Remove one instance of the specified breakpoint. When the count
291 * reaches zero, the entry is removed from the table, and the original
292 * opcode is restored.
293 *
294 * The BreakpointSet's lock must be acquired before calling here.
295 */
296static void dvmBreakpointSetRemove(BreakpointSet* pSet, Method* method,
297 unsigned int instrOffset)
298{
299 const u2* addr = method->insns + instrOffset;
300 int idx = dvmBreakpointSetFind(pSet, addr);
301
302 if (idx < 0) {
303 /* breakpoint not found in set -- unexpected */
304 if (*(u1*)addr == OP_BREAKPOINT) {
Andy McFaddenda9dc842010-05-03 16:11:20 -0700305 LOGE("Unable to restore breakpoint opcode (%s.%s +0x%x)\n",
Andy McFadden96516932009-10-28 17:39:02 -0700306 method->clazz->descriptor, method->name, instrOffset);
307 dvmAbort();
308 } else {
Andy McFaddenda9dc842010-05-03 16:11:20 -0700309 LOGW("Breakpoint was already restored? (%s.%s +0x%x)\n",
Andy McFadden96516932009-10-28 17:39:02 -0700310 method->clazz->descriptor, method->name, instrOffset);
311 }
312 } else {
313 Breakpoint* pBreak = &pSet->breakpoints[idx];
314 if (pBreak->setCount == 1) {
315 /*
316 * Must restore opcode before removing set entry.
Andy McFaddend22748a2010-04-22 17:08:11 -0700317 *
318 * If the breakpoint was never flushed, we could be ovewriting
319 * a value with the same value. Not a problem, though we
320 * could end up causing a copy-on-write here when we didn't
321 * need to. (Not worth worrying about.)
Andy McFadden96516932009-10-28 17:39:02 -0700322 */
323 dvmDexChangeDex1(method->clazz->pDvmDex, (u1*)addr,
Dan Bornstein9a1f8162010-12-01 17:02:26 -0800324 pBreak->originalOpcode);
Andy McFadden6e10b9a2010-06-14 15:24:39 -0700325 ANDROID_MEMBAR_FULL();
Andy McFadden96516932009-10-28 17:39:02 -0700326
327 if (idx != pSet->count-1) {
328 /* shift down */
329 memmove(&pSet->breakpoints[idx], &pSet->breakpoints[idx+1],
330 (pSet->count-1 - idx) * sizeof(pSet->breakpoints[0]));
331 }
332 pSet->count--;
333 pSet->breakpoints[pSet->count].addr = (u2*) 0xdecadead; // debug
334 } else {
335 pBreak->setCount--;
336 assert(pBreak->setCount > 0);
337 }
338 }
339}
340
341/*
Andy McFaddend22748a2010-04-22 17:08:11 -0700342 * Flush any breakpoints associated with methods in "clazz". We want to
343 * change the opcode, which might not have happened when the breakpoint
344 * was initially set because the class was in the process of being
345 * verified.
Andy McFadden96516932009-10-28 17:39:02 -0700346 *
347 * The BreakpointSet's lock must be acquired before calling here.
348 */
Andy McFaddend22748a2010-04-22 17:08:11 -0700349static void dvmBreakpointSetFlush(BreakpointSet* pSet, ClassObject* clazz)
Andy McFadden96516932009-10-28 17:39:02 -0700350{
Andy McFadden96516932009-10-28 17:39:02 -0700351 int i;
352 for (i = 0; i < pSet->count; i++) {
353 Breakpoint* pBreak = &pSet->breakpoints[i];
Andy McFaddend22748a2010-04-22 17:08:11 -0700354 if (pBreak->method->clazz == clazz) {
355 /*
356 * The breakpoint is associated with a method in this class.
357 * It might already be there or it might not; either way,
358 * flush it out.
359 */
360 LOGV("Flushing breakpoint at %p for %s\n",
361 pBreak->addr, clazz->descriptor);
Andy McFaddenda9dc842010-05-03 16:11:20 -0700362 if (instructionIsMagicNop(pBreak->addr)) {
Andy McFaddenda9dc842010-05-03 16:11:20 -0700363 LOGV("Refusing to flush breakpoint on %04x at %s.%s + 0x%x\n",
Carl Shapiroe3c01da2010-05-20 22:54:18 -0700364 *pBreak->addr, pBreak->method->clazz->descriptor,
365 pBreak->method->name, pBreak->addr - pBreak->method->insns);
Andy McFaddenda9dc842010-05-03 16:11:20 -0700366 } else {
367 dvmDexChangeDex1(clazz->pDvmDex, (u1*)pBreak->addr,
368 OP_BREAKPOINT);
369 }
Andy McFadden96516932009-10-28 17:39:02 -0700370 }
371 }
372}
Andy McFadden96516932009-10-28 17:39:02 -0700373
374
375/*
376 * Do any debugger-attach-time initialization.
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700377 */
378void dvmInitBreakpoints(void)
379{
Andy McFadden96516932009-10-28 17:39:02 -0700380 /* quick sanity check */
381 BreakpointSet* pSet = gDvm.breakpointSet;
382 dvmBreakpointSetLock(pSet);
383 if (dvmBreakpointSetCount(pSet) != 0) {
384 LOGW("WARNING: %d leftover breakpoints\n", dvmBreakpointSetCount(pSet));
385 /* generally not good, but we can keep going */
386 }
387 dvmBreakpointSetUnlock(pSet);
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700388}
389
390/*
391 * Add an address to the list, putting it in the first non-empty slot.
392 *
393 * Sometimes the debugger likes to add two entries for one breakpoint.
394 * We add two entries here, so that we get the right behavior when it's
395 * removed twice.
396 *
397 * This will only be run from the JDWP thread, and it will happen while
398 * we are updating the event list, which is synchronized. We're guaranteed
399 * to be the only one adding entries, and the lock ensures that nobody
400 * will be trying to remove them while we're in here.
401 *
402 * "addr" is the absolute address of the breakpoint bytecode.
403 */
Andy McFadden96516932009-10-28 17:39:02 -0700404void dvmAddBreakAddr(Method* method, unsigned int instrOffset)
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700405{
Andy McFadden96516932009-10-28 17:39:02 -0700406 BreakpointSet* pSet = gDvm.breakpointSet;
407 dvmBreakpointSetLock(pSet);
408 dvmBreakpointSetAdd(pSet, method, instrOffset);
409 dvmBreakpointSetUnlock(pSet);
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700410}
411
412/*
413 * Remove an address from the list by setting the entry to NULL.
414 *
415 * This can be called from the JDWP thread (because the debugger has
416 * cancelled the breakpoint) or from an event thread (because it's a
417 * single-shot breakpoint, e.g. "run to line"). We only get here as
418 * the result of removing an entry from the event list, which is
419 * synchronized, so it should not be possible for two threads to be
420 * updating breakpoints at the same time.
421 */
Andy McFadden96516932009-10-28 17:39:02 -0700422void dvmClearBreakAddr(Method* method, unsigned int instrOffset)
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700423{
Andy McFadden96516932009-10-28 17:39:02 -0700424 BreakpointSet* pSet = gDvm.breakpointSet;
425 dvmBreakpointSetLock(pSet);
426 dvmBreakpointSetRemove(pSet, method, instrOffset);
427 dvmBreakpointSetUnlock(pSet);
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700428}
429
Andy McFadden96516932009-10-28 17:39:02 -0700430/*
431 * Get the original opcode from under a breakpoint.
Andy McFaddenfc3d3162010-08-05 14:34:26 -0700432 *
433 * On SMP hardware it's possible one core might try to execute a breakpoint
434 * after another core has cleared it. We need to handle the case where
435 * there's no entry in the breakpoint set. (The memory barriers in the
436 * locks and in the breakpoint update code should ensure that, once we've
437 * observed the absence of a breakpoint entry, we will also now observe
438 * the restoration of the original opcode. The fact that we're holding
439 * the lock prevents other threads from confusing things further.)
Andy McFadden96516932009-10-28 17:39:02 -0700440 */
Dan Bornstein9a1f8162010-12-01 17:02:26 -0800441u1 dvmGetOriginalOpcode(const u2* addr)
Andy McFadden96516932009-10-28 17:39:02 -0700442{
443 BreakpointSet* pSet = gDvm.breakpointSet;
444 u1 orig = 0;
445
446 dvmBreakpointSetLock(pSet);
Dan Bornstein9a1f8162010-12-01 17:02:26 -0800447 if (!dvmBreakpointSetOriginalOpcode(pSet, addr, &orig)) {
Andy McFadden96516932009-10-28 17:39:02 -0700448 orig = *(u1*)addr;
449 if (orig == OP_BREAKPOINT) {
450 LOGE("GLITCH: can't find breakpoint, opcode is still set\n");
451 dvmAbort();
452 }
453 }
454 dvmBreakpointSetUnlock(pSet);
455
456 return orig;
457}
458
459/*
Andy McFaddend22748a2010-04-22 17:08:11 -0700460 * Flush any breakpoints associated with methods in "clazz".
Andy McFadden96516932009-10-28 17:39:02 -0700461 *
Andy McFaddend22748a2010-04-22 17:08:11 -0700462 * We don't want to modify the bytecode of a method before the verifier
463 * gets a chance to look at it, so we postpone opcode replacement until
464 * after verification completes.
Andy McFadden96516932009-10-28 17:39:02 -0700465 */
Andy McFaddend22748a2010-04-22 17:08:11 -0700466void dvmFlushBreakpoints(ClassObject* clazz)
Andy McFadden96516932009-10-28 17:39:02 -0700467{
468 BreakpointSet* pSet = gDvm.breakpointSet;
469
Andy McFaddend22748a2010-04-22 17:08:11 -0700470 if (pSet == NULL)
471 return;
472
473 assert(dvmIsClassVerified(clazz));
Andy McFadden96516932009-10-28 17:39:02 -0700474 dvmBreakpointSetLock(pSet);
Andy McFaddend22748a2010-04-22 17:08:11 -0700475 dvmBreakpointSetFlush(pSet, clazz);
Andy McFadden96516932009-10-28 17:39:02 -0700476 dvmBreakpointSetUnlock(pSet);
477}
Andy McFadden96516932009-10-28 17:39:02 -0700478
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700479/*
480 * Add a single step event. Currently this is a global item.
481 *
482 * We set up some initial values based on the thread's current state. This
483 * won't work well if the thread is running, so it's up to the caller to
484 * verify that it's suspended.
485 *
486 * This is only called from the JDWP thread.
487 */
488bool dvmAddSingleStep(Thread* thread, int size, int depth)
489{
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700490 StepControl* pCtrl = &gDvm.stepControl;
491
492 if (pCtrl->active && thread != pCtrl->thread) {
493 LOGW("WARNING: single-step active for %p; adding %p\n",
494 pCtrl->thread, thread);
495
496 /*
497 * Keep going, overwriting previous. This can happen if you
498 * suspend a thread in Object.wait, hit the single-step key, then
499 * switch to another thread and do the same thing again.
500 * The first thread's step is still pending.
501 *
502 * TODO: consider making single-step per-thread. Adds to the
503 * overhead, but could be useful in rare situations.
504 */
505 }
506
507 pCtrl->size = size;
508 pCtrl->depth = depth;
509 pCtrl->thread = thread;
510
511 /*
512 * We may be stepping into or over method calls, or running until we
513 * return from the current method. To make this work we need to track
514 * the current line, current method, and current stack depth. We need
515 * to be checking these after most instructions, notably those that
516 * call methods, return from methods, or are on a different line from the
517 * previous instruction.
518 *
519 * We have to start with a snapshot of the current state. If we're in
520 * an interpreted method, everything we need is in the current frame. If
521 * we're in a native method, possibly with some extra JNI frames pushed
522 * on by PushLocalFrame, we want to use the topmost native method.
523 */
524 const StackSaveArea* saveArea;
525 void* fp;
526 void* prevFp = NULL;
Ben Cheng38329f52009-07-07 14:19:20 -0700527
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700528 for (fp = thread->curFrame; fp != NULL; fp = saveArea->prevFrame) {
529 const Method* method;
530
531 saveArea = SAVEAREA_FROM_FP(fp);
532 method = saveArea->method;
533
Carl Shapirofc75f3e2010-12-07 11:43:38 -0800534 if (!dvmIsBreakFrame((u4*)fp) && !dvmIsNativeMethod(method))
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700535 break;
536 prevFp = fp;
537 }
538 if (fp == NULL) {
539 LOGW("Unexpected: step req in native-only threadid=%d\n",
540 thread->threadId);
541 return false;
542 }
543 if (prevFp != NULL) {
544 /*
545 * First interpreted frame wasn't the one at the bottom. Break
546 * frames are only inserted when calling from native->interp, so we
547 * don't need to worry about one being here.
548 */
549 LOGV("##### init step while in native method\n");
550 fp = prevFp;
Carl Shapirofc75f3e2010-12-07 11:43:38 -0800551 assert(!dvmIsBreakFrame((u4*)fp));
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700552 assert(dvmIsNativeMethod(SAVEAREA_FROM_FP(fp)->method));
553 saveArea = SAVEAREA_FROM_FP(fp);
554 }
555
556 /*
557 * Pull the goodies out. "xtra.currentPc" should be accurate since
558 * we update it on every instruction while the debugger is connected.
559 */
560 pCtrl->method = saveArea->method;
561 // Clear out any old address set
562 if (pCtrl->pAddressSet != NULL) {
563 // (discard const)
564 free((void *)pCtrl->pAddressSet);
565 pCtrl->pAddressSet = NULL;
566 }
567 if (dvmIsNativeMethod(pCtrl->method)) {
568 pCtrl->line = -1;
569 } else {
570 pCtrl->line = dvmLineNumFromPC(saveArea->method,
571 saveArea->xtra.currentPc - saveArea->method->insns);
Ben Cheng38329f52009-07-07 14:19:20 -0700572 pCtrl->pAddressSet
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700573 = dvmAddressSetForLine(saveArea->method, pCtrl->line);
574 }
575 pCtrl->frameDepth = dvmComputeVagueFrameDepth(thread, thread->curFrame);
576 pCtrl->active = true;
577
578 LOGV("##### step init: thread=%p meth=%p '%s' line=%d frameDepth=%d depth=%s size=%s\n",
579 pCtrl->thread, pCtrl->method, pCtrl->method->name,
580 pCtrl->line, pCtrl->frameDepth,
581 dvmJdwpStepDepthStr(pCtrl->depth),
582 dvmJdwpStepSizeStr(pCtrl->size));
583
584 return true;
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700585}
586
587/*
588 * Disable a single step event.
589 */
590void dvmClearSingleStep(Thread* thread)
591{
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700592 UNUSED_PARAMETER(thread);
593
594 gDvm.stepControl.active = false;
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700595}
596
buzbee9a3147c2011-03-02 15:43:48 -0800597/*
598 * The interpreter just threw. Handle any special subMode requirements.
buzbee99e3e6e2011-03-29 10:26:07 -0700599 * All interpSave state must be valid on entry.
buzbee9a3147c2011-03-02 15:43:48 -0800600 */
buzbee99e3e6e2011-03-29 10:26:07 -0700601void dvmReportExceptionThrow(Thread* self, Object* exception)
buzbee9a3147c2011-03-02 15:43:48 -0800602{
buzbee99e3e6e2011-03-29 10:26:07 -0700603 const Method* curMethod = self->interpSave.method;
buzbee9a3147c2011-03-02 15:43:48 -0800604#if defined(WITH_JIT)
605 if (self->interpBreak.ctl.subMode & kSubModeJitTraceBuild) {
buzbee99e3e6e2011-03-29 10:26:07 -0700606 dvmJitEndTraceSelect(self, self->interpSave.pc);
buzbee9a3147c2011-03-02 15:43:48 -0800607 }
608 if (self->interpBreak.ctl.breakFlags & kInterpSingleStep) {
609 /* Discard any single-step native returns to translation */
610 self->jitResumeNPC = NULL;
611 }
612#endif
613 if (self->interpBreak.ctl.subMode & kSubModeDebuggerActive) {
614 void *catchFrame;
buzbee99e3e6e2011-03-29 10:26:07 -0700615 int offset = self->interpSave.pc - curMethod->insns;
616 int catchRelPc = dvmFindCatchBlock(self, offset, exception,
buzbee9a3147c2011-03-02 15:43:48 -0800617 true, &catchFrame);
buzbee99e3e6e2011-03-29 10:26:07 -0700618 dvmDbgPostException(self->interpSave.fp, offset, catchFrame,
619 catchRelPc, exception);
buzbee9a3147c2011-03-02 15:43:48 -0800620 }
621}
622
623/*
624 * The interpreter is preparing to do an invoke (both native & normal).
buzbee99e3e6e2011-03-29 10:26:07 -0700625 * Handle any special subMode requirements. All interpSave state
626 * must be valid on entry.
buzbee9a3147c2011-03-02 15:43:48 -0800627 */
628void dvmReportInvoke(Thread* self, const Method* methodToCall)
629{
630 TRACE_METHOD_ENTER(self, methodToCall);
631}
632
633/*
634 * The interpreter is preparing to do a native invoke. Handle any
635 * special subMode requirements. NOTE: for a native invoke,
636 * dvmReportInvoke() and dvmReportPreNativeInvoke() will both
buzbee99e3e6e2011-03-29 10:26:07 -0700637 * be called prior to the invoke. All interpSave state must
638 * be valid on entry.
buzbee9a3147c2011-03-02 15:43:48 -0800639 */
buzbee99e3e6e2011-03-29 10:26:07 -0700640void dvmReportPreNativeInvoke(const Method* methodToCall, Thread* self)
buzbee9a3147c2011-03-02 15:43:48 -0800641{
642#if defined(WITH_JIT)
643 /*
644 * Actively building a trace? If so, end it now. The trace
645 * builder can't follow into or through a native method.
646 */
647 if (self->interpBreak.ctl.subMode & kSubModeJitTraceBuild) {
buzbee99e3e6e2011-03-29 10:26:07 -0700648 dvmCheckJit(self->interpSave.pc, self);
buzbee9a3147c2011-03-02 15:43:48 -0800649 }
650#endif
651 if (self->interpBreak.ctl.subMode & kSubModeDebuggerActive) {
652 Object* thisPtr = dvmGetThisPtr(self->interpSave.method,
653 self->interpSave.fp);
Andy McFaddenddab84b2011-03-28 15:23:23 -0700654 assert(thisPtr == NULL || dvmIsValidObject(thisPtr));
buzbee9a3147c2011-03-02 15:43:48 -0800655 dvmDbgPostLocationEvent(methodToCall, -1, thisPtr, DBG_METHOD_ENTRY);
656 }
657}
658
659/*
660 * The interpreter has returned from a native invoke. Handle any
buzbee99e3e6e2011-03-29 10:26:07 -0700661 * special subMode requirements. All interpSave state must be
662 * valid on entry.
buzbee9a3147c2011-03-02 15:43:48 -0800663 */
buzbee99e3e6e2011-03-29 10:26:07 -0700664void dvmReportPostNativeInvoke(const Method* methodToCall, Thread* self)
buzbee9a3147c2011-03-02 15:43:48 -0800665{
666 if (self->interpBreak.ctl.subMode & kSubModeDebuggerActive) {
667 Object* thisPtr = dvmGetThisPtr(self->interpSave.method,
668 self->interpSave.fp);
Andy McFaddenddab84b2011-03-28 15:23:23 -0700669 assert(thisPtr == NULL || dvmIsValidObject(thisPtr));
buzbee9a3147c2011-03-02 15:43:48 -0800670 dvmDbgPostLocationEvent(methodToCall, -1, thisPtr, DBG_METHOD_EXIT);
671 }
672 if (self->interpBreak.ctl.subMode & kSubModeMethodTrace) {
673 dvmFastNativeMethodTraceExit(methodToCall, self);
674 }
675}
676
677/*
678 * The interpreter has returned from a normal method. Handle any special
buzbee99e3e6e2011-03-29 10:26:07 -0700679 * subMode requirements. All interpSave state must be valid on entry.
buzbee9a3147c2011-03-02 15:43:48 -0800680 */
buzbee99e3e6e2011-03-29 10:26:07 -0700681void dvmReportReturn(Thread* self)
buzbee9a3147c2011-03-02 15:43:48 -0800682{
683 TRACE_METHOD_EXIT(self, self->interpSave.method);
684#if defined(WITH_JIT)
buzbee99e3e6e2011-03-29 10:26:07 -0700685 if (dvmIsBreakFrame(self->interpSave.fp) &&
buzbee9a3147c2011-03-02 15:43:48 -0800686 (self->interpBreak.ctl.subMode & kSubModeJitTraceBuild)) {
buzbee99e3e6e2011-03-29 10:26:07 -0700687 dvmCheckJit(self->interpSave.pc, self);
buzbee9a3147c2011-03-02 15:43:48 -0800688 }
689#endif
690}
691
692/*
693 * Update the debugger on interesting events, such as hitting a breakpoint
694 * or a single-step point. This is called from the top of the interpreter
695 * loop, before the current instruction is processed.
696 *
697 * Set "methodEntry" if we've just entered the method. This detects
698 * method exit by checking to see if the next instruction is "return".
699 *
700 * This can't catch native method entry/exit, so we have to handle that
701 * at the point of invocation. We also need to catch it in dvmCallMethod
702 * if we want to capture native->native calls made through JNI.
703 *
704 * Notes to self:
705 * - Don't want to switch to VMWAIT while posting events to the debugger.
706 * Let the debugger code decide if we need to change state.
707 * - We may want to check for debugger-induced thread suspensions on
708 * every instruction. That would make a "suspend all" more responsive
709 * and reduce the chances of multiple simultaneous events occurring.
710 * However, it could change the behavior some.
711 *
712 * TODO: method entry/exit events are probably less common than location
713 * breakpoints. We may be able to speed things up a bit if we don't query
714 * the event list unless we know there's at least one lurking within.
715 */
buzbee99e3e6e2011-03-29 10:26:07 -0700716static void updateDebugger(const Method* method, const u2* pc, const u4* fp,
buzbeee7147462011-04-13 14:10:04 -0700717 Thread* self)
buzbee9a3147c2011-03-02 15:43:48 -0800718{
719 int eventFlags = 0;
720
721 /*
722 * Update xtra.currentPc on every instruction. We need to do this if
723 * there's a chance that we could get suspended. This can happen if
724 * eventFlags != 0 here, or somebody manually requests a suspend
725 * (which gets handled at PERIOD_CHECKS time). One place where this
726 * needs to be correct is in dvmAddSingleStep().
727 */
728 dvmExportPC(pc, fp);
729
buzbeee7147462011-04-13 14:10:04 -0700730 if (self->debugIsMethodEntry) {
buzbee9a3147c2011-03-02 15:43:48 -0800731 eventFlags |= DBG_METHOD_ENTRY;
buzbeee7147462011-04-13 14:10:04 -0700732 self->debugIsMethodEntry = false;
733 }
buzbee9a3147c2011-03-02 15:43:48 -0800734
735 /*
736 * See if we have a breakpoint here.
737 *
738 * Depending on the "mods" associated with event(s) on this address,
739 * we may or may not actually send a message to the debugger.
740 */
741 if (GET_OPCODE(*pc) == OP_BREAKPOINT) {
742 LOGV("+++ breakpoint hit at %p\n", pc);
743 eventFlags |= DBG_BREAKPOINT;
744 }
745
746 /*
747 * If the debugger is single-stepping one of our threads, check to
748 * see if we're that thread and we've reached a step point.
749 */
750 const StepControl* pCtrl = &gDvm.stepControl;
751 if (pCtrl->active && pCtrl->thread == self) {
752 int frameDepth;
753 bool doStop = false;
754 const char* msg = NULL;
755
756 assert(!dvmIsNativeMethod(method));
757
758 if (pCtrl->depth == SD_INTO) {
759 /*
760 * Step into method calls. We break when the line number
761 * or method pointer changes. If we're in SS_MIN mode, we
762 * always stop.
763 */
764 if (pCtrl->method != method) {
765 doStop = true;
766 msg = "new method";
767 } else if (pCtrl->size == SS_MIN) {
768 doStop = true;
769 msg = "new instruction";
770 } else if (!dvmAddressSetGet(
771 pCtrl->pAddressSet, pc - method->insns)) {
772 doStop = true;
773 msg = "new line";
774 }
775 } else if (pCtrl->depth == SD_OVER) {
776 /*
777 * Step over method calls. We break when the line number is
778 * different and the frame depth is <= the original frame
779 * depth. (We can't just compare on the method, because we
780 * might get unrolled past it by an exception, and it's tricky
781 * to identify recursion.)
782 */
783 frameDepth = dvmComputeVagueFrameDepth(self, fp);
784 if (frameDepth < pCtrl->frameDepth) {
785 /* popped up one or more frames, always trigger */
786 doStop = true;
787 msg = "method pop";
788 } else if (frameDepth == pCtrl->frameDepth) {
789 /* same depth, see if we moved */
790 if (pCtrl->size == SS_MIN) {
791 doStop = true;
792 msg = "new instruction";
793 } else if (!dvmAddressSetGet(pCtrl->pAddressSet,
794 pc - method->insns)) {
795 doStop = true;
796 msg = "new line";
797 }
798 }
799 } else {
800 assert(pCtrl->depth == SD_OUT);
801 /*
802 * Return from the current method. We break when the frame
803 * depth pops up.
804 *
805 * This differs from the "method exit" break in that it stops
806 * with the PC at the next instruction in the returned-to
807 * function, rather than the end of the returning function.
808 */
809 frameDepth = dvmComputeVagueFrameDepth(self, fp);
810 if (frameDepth < pCtrl->frameDepth) {
811 doStop = true;
812 msg = "method pop";
813 }
814 }
815
816 if (doStop) {
817 LOGV("#####S %s\n", msg);
818 eventFlags |= DBG_SINGLE_STEP;
819 }
820 }
821
822 /*
823 * Check to see if this is a "return" instruction. JDWP says we should
824 * send the event *after* the code has been executed, but it also says
825 * the location we provide is the last instruction. Since the "return"
826 * instruction has no interesting side effects, we should be safe.
827 * (We can't just move this down to the returnFromMethod label because
828 * we potentially need to combine it with other events.)
829 *
830 * We're also not supposed to generate a method exit event if the method
831 * terminates "with a thrown exception".
832 */
833 u2 opcode = GET_OPCODE(*pc);
834 if (opcode == OP_RETURN_VOID || opcode == OP_RETURN ||
835 opcode == OP_RETURN_WIDE ||opcode == OP_RETURN_OBJECT)
836 {
837 eventFlags |= DBG_METHOD_EXIT;
838 }
839
840 /*
841 * If there's something interesting going on, see if it matches one
842 * of the debugger filters.
843 */
844 if (eventFlags != 0) {
845 Object* thisPtr = dvmGetThisPtr(method, fp);
846 if (thisPtr != NULL && !dvmIsValidObject(thisPtr)) {
847 /*
848 * TODO: remove this check if we're confident that the "this"
849 * pointer is where it should be -- slows us down, especially
850 * during single-step.
851 */
852 char* desc = dexProtoCopyMethodDescriptor(&method->prototype);
853 LOGE("HEY: invalid 'this' ptr %p (%s.%s %s)\n", thisPtr,
854 method->clazz->descriptor, method->name, desc);
855 free(desc);
856 dvmAbort();
857 }
858 dvmDbgPostLocationEvent(method, pc - method->insns, thisPtr,
859 eventFlags);
860 }
861}
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700862
863/*
864 * Recover the "this" pointer from the current interpreted method. "this"
865 * is always in "in0" for non-static methods.
866 *
867 * The "ins" start at (#of registers - #of ins). Note in0 != v0.
868 *
869 * This works because "dx" guarantees that it will work. It's probably
870 * fairly common to have a virtual method that doesn't use its "this"
871 * pointer, in which case we're potentially wasting a register. However,
872 * the debugger doesn't treat "this" as just another argument. For
873 * example, events (such as breakpoints) can be enabled for specific
874 * values of "this". There is also a separate StackFrame.ThisObject call
875 * in JDWP that is expected to work for any non-native non-static method.
876 *
877 * Because we need it when setting up debugger event filters, we want to
878 * be able to do this quickly.
879 */
880Object* dvmGetThisPtr(const Method* method, const u4* fp)
881{
882 if (dvmIsStaticMethod(method))
883 return NULL;
884 return (Object*)fp[method->registersSize - method->insSize];
885}
886
887
888#if defined(WITH_TRACKREF_CHECKS)
889/*
890 * Verify that all internally-tracked references have been released. If
891 * they haven't, print them and abort the VM.
892 *
893 * "debugTrackedRefStart" indicates how many refs were on the list when
894 * we were first invoked.
895 */
896void dvmInterpCheckTrackedRefs(Thread* self, const Method* method,
897 int debugTrackedRefStart)
898{
899 if (dvmReferenceTableEntries(&self->internalLocalRefTable)
900 != (size_t) debugTrackedRefStart)
901 {
902 char* desc;
903 Object** top;
904 int count;
905
906 count = dvmReferenceTableEntries(&self->internalLocalRefTable);
907
908 LOGE("TRACK: unreleased internal reference (prev=%d total=%d)\n",
909 debugTrackedRefStart, count);
910 desc = dexProtoCopyMethodDescriptor(&method->prototype);
911 LOGE(" current method is %s.%s %s\n", method->clazz->descriptor,
912 method->name, desc);
913 free(desc);
914 top = self->internalLocalRefTable.table + debugTrackedRefStart;
915 while (top < self->internalLocalRefTable.nextEntry) {
916 LOGE(" %p (%s)\n",
917 *top,
918 ((*top)->clazz != NULL) ? (*top)->clazz->descriptor : "");
919 top++;
920 }
921 dvmDumpThread(self, false);
922
923 dvmAbort();
924 }
925 //LOGI("TRACK OK\n");
926}
927#endif
928
929
930#ifdef LOG_INSTR
931/*
932 * Dump the v-registers. Sent to the ILOG log tag.
933 */
934void dvmDumpRegs(const Method* method, const u4* framePtr, bool inOnly)
935{
936 int i, localCount;
937
938 localCount = method->registersSize - method->insSize;
939
940 LOG(LOG_VERBOSE, LOG_TAG"i", "Registers (fp=%p):\n", framePtr);
941 for (i = method->registersSize-1; i >= 0; i--) {
942 if (i >= localCount) {
943 LOG(LOG_VERBOSE, LOG_TAG"i", " v%-2d in%-2d : 0x%08x\n",
944 i, i-localCount, framePtr[i]);
945 } else {
946 if (inOnly) {
947 LOG(LOG_VERBOSE, LOG_TAG"i", " [...]\n");
948 break;
949 }
950 const char* name = "";
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700951#if 0 // "locals" structure has changed -- need to rewrite this
Elliott Hughes8afa9df2010-07-07 14:47:25 -0700952 int j;
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700953 DexFile* pDexFile = method->clazz->pDexFile;
954 const DexCode* pDexCode = dvmGetMethodCode(method);
955 int localsSize = dexGetLocalsSize(pDexFile, pDexCode);
956 const DexLocal* locals = dvmDexGetLocals(pDexFile, pDexCode);
957 for (j = 0; j < localsSize, j++) {
958 if (locals[j].registerNum == (u4) i) {
959 name = dvmDexStringStr(locals[j].pName);
960 break;
961 }
962 }
963#endif
964 LOG(LOG_VERBOSE, LOG_TAG"i", " v%-2d : 0x%08x %s\n",
965 i, framePtr[i], name);
966 }
967 }
968}
969#endif
970
971
972/*
973 * ===========================================================================
974 * Entry point and general support functions
975 * ===========================================================================
976 */
977
Ben Cheng38329f52009-07-07 14:19:20 -0700978/*
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700979 * Construct an s4 from two consecutive half-words of switch data.
980 * This needs to check endianness because the DEX optimizer only swaps
981 * half-words in instruction stream.
982 *
983 * "switchData" must be 32-bit aligned.
984 */
985#if __BYTE_ORDER == __LITTLE_ENDIAN
986static inline s4 s4FromSwitchData(const void* switchData) {
987 return *(s4*) switchData;
988}
989#else
990static inline s4 s4FromSwitchData(const void* switchData) {
991 u2* data = switchData;
992 return data[0] | (((s4) data[1]) << 16);
Jay Freeman (saurik)ffa5c292008-11-16 13:51:51 +0000993}
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700994#endif
995
996/*
997 * Find the matching case. Returns the offset to the handler instructions.
998 *
999 * Returns 3 if we don't find a match (it's the size of the packed-switch
1000 * instruction).
1001 */
1002s4 dvmInterpHandlePackedSwitch(const u2* switchData, s4 testVal)
1003{
1004 const int kInstrLen = 3;
1005 u2 size;
1006 s4 firstKey;
1007 const s4* entries;
1008
1009 /*
1010 * Packed switch data format:
1011 * ushort ident = 0x0100 magic value
1012 * ushort size number of entries in the table
1013 * int first_key first (and lowest) switch case value
1014 * int targets[size] branch targets, relative to switch opcode
1015 *
1016 * Total size is (4+size*2) 16-bit code units.
1017 */
1018 if (*switchData++ != kPackedSwitchSignature) {
1019 /* should have been caught by verifier */
Dan Bornsteind27f3cf2011-02-23 13:07:07 -08001020 dvmThrowInternalError("bad packed switch magic");
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001021 return kInstrLen;
1022 }
1023
1024 size = *switchData++;
1025 assert(size > 0);
1026
1027 firstKey = *switchData++;
1028 firstKey |= (*switchData++) << 16;
1029
1030 if (testVal < firstKey || testVal >= firstKey + size) {
1031 LOGVV("Value %d not found in switch (%d-%d)\n",
1032 testVal, firstKey, firstKey+size-1);
1033 return kInstrLen;
1034 }
1035
1036 /* The entries are guaranteed to be aligned on a 32-bit boundary;
1037 * we can treat them as a native int array.
1038 */
1039 entries = (const s4*) switchData;
1040 assert(((u4)entries & 0x3) == 0);
1041
1042 assert(testVal - firstKey >= 0 && testVal - firstKey < size);
1043 LOGVV("Value %d found in slot %d (goto 0x%02x)\n",
1044 testVal, testVal - firstKey,
1045 s4FromSwitchData(&entries[testVal - firstKey]));
1046 return s4FromSwitchData(&entries[testVal - firstKey]);
1047}
1048
1049/*
1050 * Find the matching case. Returns the offset to the handler instructions.
1051 *
1052 * Returns 3 if we don't find a match (it's the size of the sparse-switch
1053 * instruction).
1054 */
1055s4 dvmInterpHandleSparseSwitch(const u2* switchData, s4 testVal)
1056{
1057 const int kInstrLen = 3;
Carl Shapiroe3c01da2010-05-20 22:54:18 -07001058 u2 size;
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001059 const s4* keys;
1060 const s4* entries;
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001061
1062 /*
1063 * Sparse switch data format:
1064 * ushort ident = 0x0200 magic value
1065 * ushort size number of entries in the table; > 0
1066 * int keys[size] keys, sorted low-to-high; 32-bit aligned
1067 * int targets[size] branch targets, relative to switch opcode
1068 *
1069 * Total size is (2+size*4) 16-bit code units.
1070 */
1071
1072 if (*switchData++ != kSparseSwitchSignature) {
1073 /* should have been caught by verifier */
Dan Bornsteind27f3cf2011-02-23 13:07:07 -08001074 dvmThrowInternalError("bad sparse switch magic");
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001075 return kInstrLen;
1076 }
1077
1078 size = *switchData++;
1079 assert(size > 0);
Ben Cheng38329f52009-07-07 14:19:20 -07001080
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001081 /* The keys are guaranteed to be aligned on a 32-bit boundary;
1082 * we can treat them as a native int array.
1083 */
1084 keys = (const s4*) switchData;
1085 assert(((u4)keys & 0x3) == 0);
1086
1087 /* The entries are guaranteed to be aligned on a 32-bit boundary;
1088 * we can treat them as a native int array.
1089 */
1090 entries = keys + size;
1091 assert(((u4)entries & 0x3) == 0);
1092
1093 /*
Andy McFadden62f19152009-10-21 16:59:31 -07001094 * Binary-search through the array of keys, which are guaranteed to
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001095 * be sorted low-to-high.
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001096 */
Andy McFadden62f19152009-10-21 16:59:31 -07001097 int lo = 0;
1098 int hi = size - 1;
1099 while (lo <= hi) {
1100 int mid = (lo + hi) >> 1;
1101
1102 s4 foundVal = s4FromSwitchData(&keys[mid]);
1103 if (testVal < foundVal) {
1104 hi = mid - 1;
1105 } else if (testVal > foundVal) {
1106 lo = mid + 1;
1107 } else {
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001108 LOGVV("Value %d found in entry %d (goto 0x%02x)\n",
Andy McFadden62f19152009-10-21 16:59:31 -07001109 testVal, mid, s4FromSwitchData(&entries[mid]));
1110 return s4FromSwitchData(&entries[mid]);
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001111 }
1112 }
1113
1114 LOGVV("Value %d not found in switch\n", testVal);
1115 return kInstrLen;
1116}
1117
1118/*
Andy McFadden6f214502009-06-30 16:14:30 -07001119 * Copy data for a fill-array-data instruction. On a little-endian machine
1120 * we can just do a memcpy(), on a big-endian system we have work to do.
1121 *
1122 * The trick here is that dexopt has byte-swapped each code unit, which is
1123 * exactly what we want for short/char data. For byte data we need to undo
1124 * the swap, and for 4- or 8-byte values we need to swap pieces within
1125 * each word.
1126 */
1127static void copySwappedArrayData(void* dest, const u2* src, u4 size, u2 width)
1128{
1129#if __BYTE_ORDER == __LITTLE_ENDIAN
1130 memcpy(dest, src, size*width);
1131#else
1132 int i;
1133
1134 switch (width) {
1135 case 1:
1136 /* un-swap pairs of bytes as we go */
1137 for (i = (size-1) & ~1; i >= 0; i -= 2) {
1138 ((u1*)dest)[i] = ((u1*)src)[i+1];
1139 ((u1*)dest)[i+1] = ((u1*)src)[i];
1140 }
1141 /*
1142 * "src" is padded to end on a two-byte boundary, but we don't want to
1143 * assume "dest" is, so we handle odd length specially.
1144 */
1145 if ((size & 1) != 0) {
1146 ((u1*)dest)[size-1] = ((u1*)src)[size];
1147 }
1148 break;
1149 case 2:
1150 /* already swapped correctly */
1151 memcpy(dest, src, size*width);
1152 break;
1153 case 4:
1154 /* swap word halves */
1155 for (i = 0; i < (int) size; i++) {
1156 ((u4*)dest)[i] = (src[(i << 1) + 1] << 16) | src[i << 1];
1157 }
1158 break;
1159 case 8:
1160 /* swap word halves and words */
1161 for (i = 0; i < (int) (size << 1); i += 2) {
1162 ((int*)dest)[i] = (src[(i << 1) + 3] << 16) | src[(i << 1) + 2];
1163 ((int*)dest)[i+1] = (src[(i << 1) + 1] << 16) | src[i << 1];
1164 }
1165 break;
1166 default:
1167 LOGE("Unexpected width %d in copySwappedArrayData\n", width);
1168 dvmAbort();
1169 break;
1170 }
1171#endif
1172}
1173
1174/*
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001175 * Fill the array with predefined constant values.
1176 *
1177 * Returns true if job is completed, otherwise false to indicate that
1178 * an exception has been thrown.
1179 */
The Android Open Source Project89c1feb2008-12-17 18:03:55 -08001180bool dvmInterpHandleFillArrayData(ArrayObject* arrayObj, const u2* arrayData)
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001181{
1182 u2 width;
1183 u4 size;
1184
The Android Open Source Project89c1feb2008-12-17 18:03:55 -08001185 if (arrayObj == NULL) {
Dan Bornsteind27f3cf2011-02-23 13:07:07 -08001186 dvmThrowNullPointerException(NULL);
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001187 return false;
1188 }
Barry Hayes7dc96602010-02-24 09:19:07 -08001189 assert (!IS_CLASS_FLAG_SET(((Object *)arrayObj)->clazz,
1190 CLASS_ISOBJECTARRAY));
The Android Open Source Project89c1feb2008-12-17 18:03:55 -08001191
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001192 /*
1193 * Array data table format:
1194 * ushort ident = 0x0300 magic value
1195 * ushort width width of each element in the table
1196 * uint size number of elements in the table
1197 * ubyte data[size*width] table of data values (may contain a single-byte
1198 * padding at the end)
1199 *
1200 * Total size is 4+(width * size + 1)/2 16-bit code units.
1201 */
1202 if (arrayData[0] != kArrayDataSignature) {
Dan Bornsteind27f3cf2011-02-23 13:07:07 -08001203 dvmThrowInternalError("bad array data magic");
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001204 return false;
1205 }
1206
1207 width = arrayData[1];
1208 size = arrayData[2] | (((u4)arrayData[3]) << 16);
1209
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001210 if (size > arrayObj->length) {
Dan Bornstein47f58252011-03-07 14:54:14 -08001211 dvmThrowArrayIndexOutOfBoundsException(arrayObj->length, size);
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001212 return false;
1213 }
Andy McFadden6f214502009-06-30 16:14:30 -07001214 copySwappedArrayData(arrayObj->contents, &arrayData[4], size, width);
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001215 return true;
1216}
1217
1218/*
1219 * Find the concrete method that corresponds to "methodIdx". The code in
1220 * "method" is executing invoke-method with "thisClass" as its first argument.
1221 *
1222 * Returns NULL with an exception raised on failure.
1223 */
1224Method* dvmInterpFindInterfaceMethod(ClassObject* thisClass, u4 methodIdx,
1225 const Method* method, DvmDex* methodClassDex)
1226{
1227 Method* absMethod;
1228 Method* methodToCall;
1229 int i, vtableIndex;
1230
1231 /*
1232 * Resolve the method. This gives us the abstract method from the
1233 * interface class declaration.
1234 */
1235 absMethod = dvmDexGetResolvedMethod(methodClassDex, methodIdx);
1236 if (absMethod == NULL) {
1237 absMethod = dvmResolveInterfaceMethod(method->clazz, methodIdx);
1238 if (absMethod == NULL) {
1239 LOGV("+ unknown method\n");
1240 return NULL;
1241 }
1242 }
1243
1244 /* make sure absMethod->methodIndex means what we think it means */
1245 assert(dvmIsAbstractMethod(absMethod));
1246
1247 /*
1248 * Run through the "this" object's iftable. Find the entry for
1249 * absMethod's class, then use absMethod->methodIndex to find
1250 * the method's entry. The value there is the offset into our
1251 * vtable of the actual method to execute.
1252 *
1253 * The verifier does not guarantee that objects stored into
1254 * interface references actually implement the interface, so this
1255 * check cannot be eliminated.
1256 */
1257 for (i = 0; i < thisClass->iftableCount; i++) {
1258 if (thisClass->iftable[i].clazz == absMethod->clazz)
1259 break;
1260 }
1261 if (i == thisClass->iftableCount) {
1262 /* impossible in verified DEX, need to check for it in unverified */
Dan Bornstein70b00ab2011-02-23 14:11:27 -08001263 dvmThrowIncompatibleClassChangeError("interface not implemented");
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001264 return NULL;
1265 }
1266
1267 assert(absMethod->methodIndex <
1268 thisClass->iftable[i].clazz->virtualMethodCount);
1269
1270 vtableIndex =
1271 thisClass->iftable[i].methodIndexArray[absMethod->methodIndex];
1272 assert(vtableIndex >= 0 && vtableIndex < thisClass->vtableCount);
1273 methodToCall = thisClass->vtable[vtableIndex];
1274
1275#if 0
1276 /* this can happen when there's a stale class file */
1277 if (dvmIsAbstractMethod(methodToCall)) {
Dan Bornsteind27f3cf2011-02-23 13:07:07 -08001278 dvmThrowAbstractMethodError("interface method not implemented");
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001279 return NULL;
1280 }
1281#else
1282 assert(!dvmIsAbstractMethod(methodToCall) ||
1283 methodToCall->nativeFunc != NULL);
1284#endif
1285
1286 LOGVV("+++ interface=%s.%s concrete=%s.%s\n",
1287 absMethod->clazz->descriptor, absMethod->name,
1288 methodToCall->clazz->descriptor, methodToCall->name);
1289 assert(methodToCall != NULL);
1290
1291 return methodToCall;
1292}
1293
1294
Andy McFaddenb51ea112009-05-08 16:50:17 -07001295
1296/*
1297 * Helpers for dvmThrowVerificationError().
1298 *
1299 * Each returns a newly-allocated string.
1300 */
1301#define kThrowShow_accessFromClass 1
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001302static char* classNameFromIndex(const Method* method, int ref,
1303 VerifyErrorRefType refType, int flags)
Andy McFaddenb51ea112009-05-08 16:50:17 -07001304{
1305 static const int kBufLen = 256;
1306 const DvmDex* pDvmDex = method->clazz->pDvmDex;
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001307
1308 if (refType == VERIFY_ERROR_REF_FIELD) {
1309 /* get class ID from field ID */
1310 const DexFieldId* pFieldId = dexGetFieldId(pDvmDex->pDexFile, ref);
1311 ref = pFieldId->classIdx;
1312 } else if (refType == VERIFY_ERROR_REF_METHOD) {
1313 /* get class ID from method ID */
1314 const DexMethodId* pMethodId = dexGetMethodId(pDvmDex->pDexFile, ref);
1315 ref = pMethodId->classIdx;
1316 }
1317
Andy McFaddenb51ea112009-05-08 16:50:17 -07001318 const char* className = dexStringByTypeIdx(pDvmDex->pDexFile, ref);
Elliott Hughes50169662010-11-22 13:14:23 -08001319 char* dotClassName = dvmHumanReadableDescriptor(className);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001320 if (flags == 0)
1321 return dotClassName;
1322
1323 char* result = (char*) malloc(kBufLen);
1324
1325 if ((flags & kThrowShow_accessFromClass) != 0) {
Elliott Hughes50169662010-11-22 13:14:23 -08001326 char* dotFromName =
1327 dvmHumanReadableDescriptor(method->clazz->descriptor);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001328 snprintf(result, kBufLen, "tried to access class %s from class %s",
1329 dotClassName, dotFromName);
1330 free(dotFromName);
1331 } else {
1332 assert(false); // should've been caught above
1333 result[0] = '\0';
1334 }
1335
1336 free(dotClassName);
1337 return result;
1338}
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001339static char* fieldNameFromIndex(const Method* method, int ref,
1340 VerifyErrorRefType refType, int flags)
Andy McFaddenb51ea112009-05-08 16:50:17 -07001341{
1342 static const int kBufLen = 256;
1343 const DvmDex* pDvmDex = method->clazz->pDvmDex;
1344 const DexFieldId* pFieldId;
1345 const char* className;
1346 const char* fieldName;
1347
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001348 if (refType != VERIFY_ERROR_REF_FIELD) {
1349 LOGW("Expected ref type %d, got %d\n", VERIFY_ERROR_REF_FIELD, refType);
1350 return NULL; /* no message */
1351 }
1352
Andy McFaddenb51ea112009-05-08 16:50:17 -07001353 pFieldId = dexGetFieldId(pDvmDex->pDexFile, ref);
1354 className = dexStringByTypeIdx(pDvmDex->pDexFile, pFieldId->classIdx);
1355 fieldName = dexStringById(pDvmDex->pDexFile, pFieldId->nameIdx);
1356
Elliott Hughes50169662010-11-22 13:14:23 -08001357 char* dotName = dvmHumanReadableDescriptor(className);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001358 char* result = (char*) malloc(kBufLen);
1359
1360 if ((flags & kThrowShow_accessFromClass) != 0) {
Elliott Hughes50169662010-11-22 13:14:23 -08001361 char* dotFromName =
1362 dvmHumanReadableDescriptor(method->clazz->descriptor);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001363 snprintf(result, kBufLen, "tried to access field %s.%s from class %s",
1364 dotName, fieldName, dotFromName);
1365 free(dotFromName);
1366 } else {
1367 snprintf(result, kBufLen, "%s.%s", dotName, fieldName);
1368 }
1369
1370 free(dotName);
1371 return result;
1372}
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001373static char* methodNameFromIndex(const Method* method, int ref,
1374 VerifyErrorRefType refType, int flags)
Andy McFaddenb51ea112009-05-08 16:50:17 -07001375{
1376 static const int kBufLen = 384;
1377 const DvmDex* pDvmDex = method->clazz->pDvmDex;
1378 const DexMethodId* pMethodId;
1379 const char* className;
1380 const char* methodName;
1381
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001382 if (refType != VERIFY_ERROR_REF_METHOD) {
1383 LOGW("Expected ref type %d, got %d\n", VERIFY_ERROR_REF_METHOD,refType);
1384 return NULL; /* no message */
1385 }
1386
Andy McFaddenb51ea112009-05-08 16:50:17 -07001387 pMethodId = dexGetMethodId(pDvmDex->pDexFile, ref);
1388 className = dexStringByTypeIdx(pDvmDex->pDexFile, pMethodId->classIdx);
1389 methodName = dexStringById(pDvmDex->pDexFile, pMethodId->nameIdx);
1390
Elliott Hughes50169662010-11-22 13:14:23 -08001391 char* dotName = dvmHumanReadableDescriptor(className);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001392 char* result = (char*) malloc(kBufLen);
1393
1394 if ((flags & kThrowShow_accessFromClass) != 0) {
Elliott Hughes50169662010-11-22 13:14:23 -08001395 char* dotFromName =
1396 dvmHumanReadableDescriptor(method->clazz->descriptor);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001397 char* desc = dexProtoCopyMethodDescriptor(&method->prototype);
1398 snprintf(result, kBufLen,
1399 "tried to access method %s.%s:%s from class %s",
1400 dotName, methodName, desc, dotFromName);
1401 free(dotFromName);
1402 free(desc);
1403 } else {
1404 snprintf(result, kBufLen, "%s.%s", dotName, methodName);
1405 }
1406
1407 free(dotName);
1408 return result;
1409}
1410
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001411/*
Andy McFadden3a1aedb2009-05-07 13:30:23 -07001412 * Throw an exception for a problem identified by the verifier.
1413 *
1414 * This is used by the invoke-verification-error instruction. It always
1415 * throws an exception.
1416 *
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001417 * "kind" indicates the kind of failure encountered by the verifier. It
1418 * has two parts, an error code and an indication of the reference type.
Andy McFadden3a1aedb2009-05-07 13:30:23 -07001419 */
Andy McFaddenb51ea112009-05-08 16:50:17 -07001420void dvmThrowVerificationError(const Method* method, int kind, int ref)
Andy McFadden3a1aedb2009-05-07 13:30:23 -07001421{
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001422 const int typeMask = 0xff << kVerifyErrorRefTypeShift;
1423 VerifyError errorKind = kind & ~typeMask;
1424 VerifyErrorRefType refType = kind >> kVerifyErrorRefTypeShift;
Dan Bornsteina3b35122011-03-03 16:17:37 -08001425 ClassObject* exceptionClass = gDvm.exVerifyError;
Andy McFaddenb51ea112009-05-08 16:50:17 -07001426 char* msg = NULL;
1427
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001428 switch ((VerifyError) errorKind) {
Andy McFaddenb51ea112009-05-08 16:50:17 -07001429 case VERIFY_ERROR_NO_CLASS:
Dan Bornsteina3b35122011-03-03 16:17:37 -08001430 exceptionClass = gDvm.exNoClassDefFoundError;
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001431 msg = classNameFromIndex(method, ref, refType, 0);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001432 break;
1433 case VERIFY_ERROR_NO_FIELD:
Dan Bornsteina3b35122011-03-03 16:17:37 -08001434 exceptionClass = gDvm.exNoSuchFieldError;
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001435 msg = fieldNameFromIndex(method, ref, refType, 0);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001436 break;
1437 case VERIFY_ERROR_NO_METHOD:
Dan Bornsteina3b35122011-03-03 16:17:37 -08001438 exceptionClass = gDvm.exNoSuchMethodError;
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001439 msg = methodNameFromIndex(method, ref, refType, 0);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001440 break;
1441 case VERIFY_ERROR_ACCESS_CLASS:
Dan Bornsteina3b35122011-03-03 16:17:37 -08001442 exceptionClass = gDvm.exIllegalAccessError;
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001443 msg = classNameFromIndex(method, ref, refType,
1444 kThrowShow_accessFromClass);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001445 break;
1446 case VERIFY_ERROR_ACCESS_FIELD:
Dan Bornsteina3b35122011-03-03 16:17:37 -08001447 exceptionClass = gDvm.exIllegalAccessError;
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001448 msg = fieldNameFromIndex(method, ref, refType,
1449 kThrowShow_accessFromClass);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001450 break;
1451 case VERIFY_ERROR_ACCESS_METHOD:
Dan Bornsteina3b35122011-03-03 16:17:37 -08001452 exceptionClass = gDvm.exIllegalAccessError;
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001453 msg = methodNameFromIndex(method, ref, refType,
1454 kThrowShow_accessFromClass);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001455 break;
1456 case VERIFY_ERROR_CLASS_CHANGE:
Dan Bornsteina3b35122011-03-03 16:17:37 -08001457 exceptionClass = gDvm.exIncompatibleClassChangeError;
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001458 msg = classNameFromIndex(method, ref, refType, 0);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001459 break;
1460 case VERIFY_ERROR_INSTANTIATION:
Dan Bornsteina3b35122011-03-03 16:17:37 -08001461 exceptionClass = gDvm.exInstantiationError;
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001462 msg = classNameFromIndex(method, ref, refType, 0);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001463 break;
1464
1465 case VERIFY_ERROR_GENERIC:
1466 /* generic VerifyError; use default exception, no message */
1467 break;
1468 case VERIFY_ERROR_NONE:
1469 /* should never happen; use default exception */
1470 assert(false);
1471 msg = strdup("weird - no error specified");
1472 break;
1473
1474 /* no default clause -- want warning if enum updated */
1475 }
1476
Dan Bornstein0b8b2932011-03-04 11:53:40 -08001477 dvmThrowException(exceptionClass, msg);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001478 free(msg);
Andy McFadden3a1aedb2009-05-07 13:30:23 -07001479}
1480
Andy McFadden3a1aedb2009-05-07 13:30:23 -07001481/*
buzbee9a3147c2011-03-02 15:43:48 -08001482 * Update interpBreak. If there is an active break when
1483 * we're done, set altHandlerTable. Otherwise, revert to
1484 * the non-breaking table base.
buzbeecb3081f2011-01-14 13:37:31 -08001485 */
buzbee9a3147c2011-03-02 15:43:48 -08001486void dvmUpdateInterpBreak(Thread* thread, int newBreak, int newMode,
1487 bool enable)
buzbeecb3081f2011-01-14 13:37:31 -08001488{
buzbee9a3147c2011-03-02 15:43:48 -08001489 InterpBreak oldValue, newValue;
1490
1491 // Do not use this routine for suspend updates. See below.
1492 assert((newBreak & kInterpSuspendBreak) == 0);
buzbeecb3081f2011-01-14 13:37:31 -08001493
1494 do {
buzbee9a3147c2011-03-02 15:43:48 -08001495 oldValue = newValue = thread->interpBreak;
1496 if (enable) {
1497 newValue.ctl.breakFlags |= newBreak;
1498 newValue.ctl.subMode |= newMode;
1499 } else {
1500 newValue.ctl.breakFlags &= ~newBreak;
1501 newValue.ctl.subMode &= ~newMode;
1502 }
1503 newValue.ctl.curHandlerTable = (newValue.ctl.breakFlags) ?
1504 thread->altHandlerTable : thread->mainHandlerTable;
1505 } while (dvmQuasiAtomicCas64(oldValue.all, newValue.all,
1506 &thread->interpBreak.all) != 0);
1507}
1508
1509/*
1510 * Update the normal and debugger suspend counts for a thread.
1511 * threadSuspendCount must be acquired before calling this to
1512 * ensure a clean update of suspendCount, dbgSuspendCount and
1513 * sumThreadSuspendCount. suspendCount & dbgSuspendCount must
1514 * use the atomic update to avoid conflict with writes to the
1515 * other fields in interpBreak.
1516 *
1517 * CLEANUP TODO: Currently only the JIT is using sumThreadSuspendCount.
1518 * Move under WITH_JIT ifdefs.
1519*/
1520void dvmAddToSuspendCounts(Thread* thread, int delta, int dbgDelta)
1521{
1522 InterpBreak oldValue, newValue;
1523
1524 do {
1525 oldValue = newValue = thread->interpBreak;
1526 newValue.ctl.suspendCount += delta;
1527 newValue.ctl.dbgSuspendCount += dbgDelta;
1528 assert(newValue.ctl.suspendCount >= newValue.ctl.dbgSuspendCount);
1529 if (newValue.ctl.suspendCount > 0) {
1530 newValue.ctl.breakFlags |= kInterpSuspendBreak;
1531 } else {
1532 newValue.ctl.breakFlags &= ~kInterpSuspendBreak;
1533 }
1534 newValue.ctl.curHandlerTable = (newValue.ctl.breakFlags) ?
1535 thread->altHandlerTable : thread->mainHandlerTable;
1536 } while (dvmQuasiAtomicCas64(oldValue.all, newValue.all,
1537 &thread->interpBreak.all) != 0);
1538
1539 // Update the global suspend count total
1540 gDvm.sumThreadSuspendCount += delta;
1541}
1542
1543/*
1544 * Update interpBreak for all threads.
1545 */
1546void dvmUpdateAllInterpBreak(int newBreak, int newMode, bool enable)
1547{
1548 Thread* self = dvmThreadSelf();
1549 Thread* thread;
1550
1551 dvmLockThreadList(self);
1552 for (thread = gDvm.threadList; thread != NULL; thread = thread->next) {
1553 dvmUpdateInterpBreak(thread, newBreak, newMode, enable);
1554 }
1555 dvmUnlockThreadList();
buzbeecb3081f2011-01-14 13:37:31 -08001556}
1557
1558/*
buzbee99e3e6e2011-03-29 10:26:07 -07001559 * Do a sanity check on interpreter state saved to Thread.
1560 * A failure here doesn't necessarily mean that something is wrong,
1561 * so this code should only be used during development to suggest
1562 * a possible problem.
1563 */
1564void dvmCheckInterpStateConsistency()
1565{
1566 Thread* self = dvmThreadSelf();
1567 Thread* thread;
1568 uint8_t breakFlags;
1569 uint8_t subMode;
1570 void* handlerTable;
1571
1572 dvmLockThreadList(self);
1573 breakFlags = self->interpBreak.ctl.breakFlags;
1574 subMode = self->interpBreak.ctl.subMode;
1575 handlerTable = self->interpBreak.ctl.curHandlerTable;
1576 for (thread = gDvm.threadList; thread != NULL; thread = thread->next) {
1577 if (subMode != thread->interpBreak.ctl.subMode) {
1578 LOGD("Warning: subMode mismatch - 0x%x:0x%x, tid[%d]",
1579 subMode,thread->interpBreak.ctl.subMode,thread->threadId);
1580 }
1581 if (breakFlags != thread->interpBreak.ctl.breakFlags) {
1582 LOGD("Warning: breakFlags mismatch - 0x%x:0x%x, tid[%d]",
1583 breakFlags,thread->interpBreak.ctl.breakFlags,thread->threadId);
1584 }
1585 if (handlerTable != thread->interpBreak.ctl.curHandlerTable) {
1586 LOGD("Warning: curHandlerTable mismatch - 0x%x:0x%x, tid[%d]",
1587 (int)handlerTable,(int)thread->interpBreak.ctl.curHandlerTable,
1588 thread->threadId);
1589 }
1590#if defined(WITH_JIT)
1591 if (thread->pJitProfTable != gDvmJit.pProfTable) {
1592 LOGD("Warning: pJitProfTable mismatch - 0x%x:0x%x, tid[%d]",
1593 (int)thread->pJitProfTable,(int)gDvmJit.pProfTable,
1594 thread->threadId);
1595 }
1596 if (thread->jitThreshold != gDvmJit.threshold) {
1597 LOGD("Warning: jitThreshold mismatch - 0x%x:0x%x, tid[%d]",
1598 (int)thread->jitThreshold,(int)gDvmJit.threshold,
1599 thread->threadId);
1600 }
1601#endif
1602 }
1603 dvmUnlockThreadList();
1604}
1605
1606/*
buzbee94d65252011-03-24 16:41:03 -07001607 * Arm a safepoint callback for a thread. If funct is null,
1608 * clear any pending callback.
1609 * TODO: only gc is currently using this feature, and will have
1610 * at most a single outstanding callback request. Until we need
1611 * something more capable and flexible, enforce this limit.
1612 */
1613void dvmArmSafePointCallback(Thread* thread, SafePointCallback funct,
1614 void* arg)
1615{
1616 dvmLockMutex(&thread->callbackMutex);
1617 if ((funct == NULL) || (thread->callback == NULL)) {
1618 thread->callback = funct;
1619 thread->callbackArg = arg;
1620 dvmUpdateInterpBreak(thread, kInterpSafePointCallback,
1621 kSubModeNormal, (funct != NULL));
1622 } else {
1623 // Already armed. Different?
1624 if ((funct != thread->callback) ||
1625 (arg != thread->callbackArg)) {
1626 // Yes - report failure and die
1627 LOGE("ArmSafePointCallback failed, thread %d", thread->threadId);
1628 dvmUnlockMutex(&thread->callbackMutex);
1629 dvmAbort();
1630 }
1631 }
1632 dvmUnlockMutex(&thread->callbackMutex);
1633}
1634
1635/*
buzbee9f601a92011-02-11 17:48:20 -08001636 * One-time initialization at thread creation. Here we initialize
1637 * useful constants.
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001638 */
buzbee9f601a92011-02-11 17:48:20 -08001639void dvmInitInterpreterState(Thread* self)
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001640{
Ben Chengba4fc8b2009-06-01 13:00:29 -07001641#if defined(WITH_JIT)
1642 /* Interpreter entry points from compiled code */
1643 extern void dvmJitToInterpNormal();
1644 extern void dvmJitToInterpNoChain();
1645 extern void dvmJitToInterpPunt();
1646 extern void dvmJitToInterpSingleStep();
Ben Cheng40094c12010-02-24 20:58:44 -08001647 extern void dvmJitToInterpTraceSelect();
Jeff Hao97319a82009-08-12 16:57:15 -07001648#if defined(WITH_SELF_VERIFICATION)
Ben Cheng40094c12010-02-24 20:58:44 -08001649 extern void dvmJitToInterpBackwardBranch();
Jeff Hao97319a82009-08-12 16:57:15 -07001650#endif
Ben Cheng38329f52009-07-07 14:19:20 -07001651 /*
Ben Chengba4fc8b2009-06-01 13:00:29 -07001652 * Reserve a static entity here to quickly setup runtime contents as
1653 * gcc will issue block copy instructions.
1654 */
1655 static struct JitToInterpEntries jitToInterpEntries = {
1656 dvmJitToInterpNormal,
1657 dvmJitToInterpNoChain,
1658 dvmJitToInterpPunt,
1659 dvmJitToInterpSingleStep,
Ben Cheng40094c12010-02-24 20:58:44 -08001660 dvmJitToInterpTraceSelect,
Jeff Hao97319a82009-08-12 16:57:15 -07001661#if defined(WITH_SELF_VERIFICATION)
Ben Cheng40094c12010-02-24 20:58:44 -08001662 dvmJitToInterpBackwardBranch,
buzbee9f601a92011-02-11 17:48:20 -08001663#else
1664 NULL,
Jeff Hao97319a82009-08-12 16:57:15 -07001665#endif
Ben Chengba4fc8b2009-06-01 13:00:29 -07001666 };
buzbee9f601a92011-02-11 17:48:20 -08001667#endif
Ben Cheng7a0bcd02010-01-22 16:45:45 -08001668
buzbee9f601a92011-02-11 17:48:20 -08001669 // Begin initialization
1670 self->cardTable = gDvm.biasedCardTableBase;
buzbee9f601a92011-02-11 17:48:20 -08001671#if defined(WITH_JIT)
buzbee9a3147c2011-03-02 15:43:48 -08001672 // One-time initializations
buzbee9f601a92011-02-11 17:48:20 -08001673 self->jitToInterpEntries = jitToInterpEntries;
1674 self->icRechainCount = PREDICTED_CHAIN_COUNTER_RECHAIN;
buzbee9f601a92011-02-11 17:48:20 -08001675 self->pProfileCountdown = &gDvmJit.profileCountdown;
buzbee9a3147c2011-03-02 15:43:48 -08001676 // Jit state that can change
buzbee99e3e6e2011-03-29 10:26:07 -07001677 dvmJitUpdateThreadStateSingle(self);
buzbee9f601a92011-02-11 17:48:20 -08001678#endif
buzbee99e3e6e2011-03-29 10:26:07 -07001679}
buzbee9f601a92011-02-11 17:48:20 -08001680
buzbee99e3e6e2011-03-29 10:26:07 -07001681/*
1682 * For a newly-created thread, we need to start off with interpBreak
1683 * set to any existing global modes. The caller must hold the
1684 * thread list lock.
1685 */
1686void dvmInitializeInterpBreak(Thread* thread)
1687{
1688 u1 flags = 0;
1689 u1 subModes = 0;
1690
1691 if (gDvm.instructionCountEnableCount > 0) {
1692 flags |= kInterpInstCountBreak;
1693 subModes |= kSubModeInstCounting;
1694 }
1695 if (dvmIsMethodTraceActive()) {
1696 subModes |= kSubModeMethodTrace;
1697 }
1698 if (gDvm.debuggerActive) {
1699 flags |= kInterpDebugBreak;
1700 subModes |= kSubModeDebuggerActive;
1701 }
1702 dvmUpdateInterpBreak(thread, flags, subModes, true);
buzbee9f601a92011-02-11 17:48:20 -08001703}
1704
buzbeea7d59bb2011-02-24 09:38:17 -08001705/*
1706 * Inter-instruction handler invoked in between instruction interpretations
1707 * to handle exceptional events such as debugging housekeeping, instruction
buzbee9a3147c2011-03-02 15:43:48 -08001708 * count profiling, JIT trace building, etc. Dalvik PC has been exported
1709 * prior to call, but Thread copy of dPC & fp are not current.
buzbeea7d59bb2011-02-24 09:38:17 -08001710 */
buzbee94d65252011-03-24 16:41:03 -07001711void dvmCheckBefore(const u2 *pc, u4 *fp, Thread* self)
buzbeea7d59bb2011-02-24 09:38:17 -08001712{
buzbee9a3147c2011-03-02 15:43:48 -08001713 const Method* method = self->interpSave.method;
1714 assert(self->interpBreak.ctl.breakFlags != 0);
1715 assert(pc >= method->insns && pc <
1716 method->insns + dvmGetMethodInsnsSize(method));
1717
1718#if 0
1719 /*
1720 * When we hit a specific method, enable verbose instruction logging.
1721 * Sometimes it's helpful to use the debugger attach as a trigger too.
1722 */
1723 if (*pIsMethodEntry) {
1724 static const char* cd = "Landroid/test/Arithmetic;";
1725 static const char* mn = "shiftTest2";
1726 static const char* sg = "()V";
1727
1728 if (/*self->interpBreak.ctl.subMode & kSubModeDebuggerActive &&*/
1729 strcmp(method->clazz->descriptor, cd) == 0 &&
1730 strcmp(method->name, mn) == 0 &&
1731 strcmp(method->shorty, sg) == 0)
1732 {
1733 LOGW("Reached %s.%s, enabling verbose mode\n",
1734 method->clazz->descriptor, method->name);
1735 android_setMinPriority(LOG_TAG"i", ANDROID_LOG_VERBOSE);
1736 dumpRegs(method, fp, true);
1737 }
1738
1739 if (!gDvm.debuggerActive)
1740 *pIsMethodEntry = false;
1741 }
1742#endif
1743
buzbee94d65252011-03-24 16:41:03 -07001744 /* Safe point handling */
1745 if (self->interpBreak.ctl.suspendCount ||
1746 (self->interpBreak.ctl.breakFlags & kInterpSafePointCallback)) {
buzbeec4a8caf2011-03-24 12:56:41 -07001747 // Are we are a safe point?
1748 int flags;
1749 flags = dexGetFlagsFromOpcode(dexOpcodeFromCodeUnit(*pc));
1750 if (flags & VERIFY_GC_INST_MASK) {
buzbee94d65252011-03-24 16:41:03 -07001751 // Yes, at a safe point. Pending callback?
1752 if (self->interpBreak.ctl.breakFlags & kInterpSafePointCallback) {
1753 SafePointCallback callback;
1754 void* arg;
1755 // Get consistent funct/arg pair
1756 dvmLockMutex(&self->callbackMutex);
1757 callback = self->callback;
1758 arg = self->callbackArg;
1759 dvmUnlockMutex(&self->callbackMutex);
1760 // Update Thread structure
1761 self->interpSave.pc = pc;
1762 self->interpSave.fp = fp;
1763 if (callback != NULL) {
1764 // Do the callback
1765 if (!callback(self,arg)) {
1766 // disarm
1767 dvmArmSafePointCallback(self, NULL, NULL);
1768 }
1769 }
1770 }
1771 // Need to suspend?
1772 if (self->interpBreak.ctl.suspendCount) {
1773 dvmExportPC(pc, fp);
1774 dvmCheckSuspendPending(self);
1775 }
buzbeec4a8caf2011-03-24 12:56:41 -07001776 }
buzbee9a3147c2011-03-02 15:43:48 -08001777 }
1778
1779 if (self->interpBreak.ctl.subMode & kSubModeDebuggerActive) {
buzbeee7147462011-04-13 14:10:04 -07001780 updateDebugger(method, pc, fp, self);
buzbee9a3147c2011-03-02 15:43:48 -08001781 }
1782 if (gDvm.instructionCountEnableCount != 0) {
1783 /*
1784 * Count up the #of executed instructions. This isn't synchronized
1785 * for thread-safety; if we need that we should make this
1786 * thread-local and merge counts into the global area when threads
1787 * exit (perhaps suspending all other threads GC-style and pulling
1788 * the data out of them).
1789 */
1790 gDvm.executedInstrCounts[GET_OPCODE(*pc)]++;
1791 }
1792
1793
1794#if defined(WITH_TRACKREF_CHECKS)
1795 dvmInterpCheckTrackedRefs(self, method,
1796 self->interpSave.debugTrackedRefStart);
1797#endif
1798
1799#if defined(WITH_JIT)
1800 // Does the JIT need anything done now?
1801 if (self->interpBreak.ctl.breakFlags & kInterpJitBreak) {
1802 // Are we building a trace?
1803 if (self->interpBreak.ctl.subMode & kSubModeJitTraceBuild) {
1804 dvmCheckJit(pc, self);
1805 }
1806
1807#if defined(WITH_SELF_VERIFICATION)
1808 // Are we replaying a trace?
1809 if (self->interpBreak.ctl.subMode & kSubModeJitSV) {
1810 dvmCheckSelfVerification(pc, self);
1811 }
1812#endif
1813 }
1814#endif
1815
1816 /*
1817 * SingleStep processing. NOTE: must be the last here to allow
1818 * preceeding special case handler to manipulate single-step count.
1819 */
1820 if (self->interpBreak.ctl.breakFlags & kInterpSingleStep) {
1821 if (self->singleStepCount == 0) {
1822 // We've exhausted our single step count
1823 dvmUpdateInterpBreak(self, kInterpSingleStep, kSubModeNormal,
1824 false /* remove */);
1825#if defined(WITH_JIT)
1826#if 0
1827 /*
1828 * For debugging. If jitResumeDPC is non-zero, then
1829 * we expect to return to a trace in progress. There
1830 * are valid reasons why we wouldn't (such as an exception
1831 * throw), but here we can keep track.
1832 */
1833 if (self->jitResumeDPC != NULL) {
1834 if (self->jitResumeDPC == pc) {
1835 if (self->jitResumeNPC != NULL) {
1836 LOGD("SS return to trace - pc:0x%x to 0x:%x",
1837 (int)pc, (int)self->jitResumeNPC);
1838 } else {
1839 LOGD("SS return to interp - pc:0x%x",(int)pc);
1840 }
1841 } else {
1842 LOGD("SS failed to return. Expected 0x%x, now at 0x%x",
1843 (int)self->jitResumeDPC, (int)pc);
1844 }
1845 }
1846#endif
1847 // If we've got a native return and no other reasons to
1848 // remain in singlestep/break mode, do a long jump
1849 if (self->jitResumeNPC != NULL &&
1850 self->interpBreak.ctl.breakFlags == 0) {
1851 assert(self->jitResumeDPC == pc);
1852 self->jitResumeDPC = NULL;
1853 dvmJitResumeTranslation(self, pc, fp);
1854 // Doesn't return
1855 dvmAbort();
1856 }
1857 self->jitResumeDPC = NULL;
buzbee7209bdd2011-03-31 15:38:34 -07001858 self->inJitCodeCache = NULL;
buzbee9a3147c2011-03-02 15:43:48 -08001859#endif
1860 } else {
1861 self->singleStepCount--;
1862#if defined(WITH_JIT)
1863 if ((self->singleStepCount > 0) && (self->jitResumeNPC != NULL)) {
1864 /*
1865 * Direct return to an existing translation following a
1866 * single step is valid only if we step once. If we're
1867 * here, an additional step was added so we need to invalidate
1868 * the return to translation.
1869 */
1870 self->jitResumeNPC = NULL;
buzbee7209bdd2011-03-31 15:38:34 -07001871 self->inJitCodeCache = NULL;
buzbee9a3147c2011-03-02 15:43:48 -08001872 }
1873#endif
1874 }
1875 }
buzbeea7d59bb2011-02-24 09:38:17 -08001876}
buzbee9f601a92011-02-11 17:48:20 -08001877
1878/*
buzbee9a3147c2011-03-02 15:43:48 -08001879 * Main interpreter loop entry point.
buzbee9f601a92011-02-11 17:48:20 -08001880 *
1881 * This begins executing code at the start of "method". On exit, "pResult"
1882 * holds the return value of the method (or, if "method" returns NULL, it
1883 * holds an undefined value).
1884 *
1885 * The interpreted stack frame, which holds the method arguments, has
1886 * already been set up.
1887 */
1888void dvmInterpret(Thread* self, const Method* method, JValue* pResult)
1889{
buzbee9f601a92011-02-11 17:48:20 -08001890 InterpSaveState interpSaveState;
buzbee9a3147c2011-03-02 15:43:48 -08001891 int savedBreakFlags;
1892 int savedSubModes;
1893
buzbee9f601a92011-02-11 17:48:20 -08001894#if defined(WITH_JIT)
1895 /* Target-specific save/restore */
1896 extern void dvmJitCalleeSave(double *saveArea);
1897 extern void dvmJitCalleeRestore(double *saveArea);
1898 double calleeSave[JIT_CALLEE_SAVE_DOUBLE_COUNT];
Ben Cheng7a2697d2010-06-07 13:44:23 -07001899 /*
1900 * If the previous VM left the code cache through single-stepping the
1901 * inJitCodeCache flag will be set when the VM is re-entered (for example,
1902 * in self-verification mode we single-step NEW_INSTANCE which may re-enter
1903 * the VM through findClassFromLoaderNoInit). Because of that, we cannot
1904 * assert that self->inJitCodeCache is NULL here.
1905 */
Ben Chengba4fc8b2009-06-01 13:00:29 -07001906#endif
1907
buzbee9f601a92011-02-11 17:48:20 -08001908 /*
1909 * Save interpreter state from previous activation, linking
1910 * new to last.
1911 */
1912 interpSaveState = self->interpSave;
1913 self->interpSave.prev = &interpSaveState;
buzbee9a3147c2011-03-02 15:43:48 -08001914 /*
1915 * Strip out and save any flags that should not be inherited by
1916 * nested interpreter activation.
1917 */
1918 savedBreakFlags = self->interpBreak.ctl.breakFlags & LOCAL_BREAKFLAGS;
1919 savedSubModes = self->interpBreak.ctl.subMode & LOCAL_SUBMODE;
1920 if (savedBreakFlags | savedSubModes) {
1921 dvmUpdateInterpBreak(self, savedBreakFlags, savedSubModes,
1922 false /*disable*/);
1923 }
buzbee9f601a92011-02-11 17:48:20 -08001924#if defined(WITH_JIT)
1925 dvmJitCalleeSave(calleeSave);
1926#endif
1927
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001928
1929#if defined(WITH_TRACKREF_CHECKS)
buzbeeef5db622011-02-22 14:01:46 -08001930 self->interpSave.debugTrackedRefStart =
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001931 dvmReferenceTableEntries(&self->internalLocalRefTable);
1932#endif
buzbee9f601a92011-02-11 17:48:20 -08001933 self->debugIsMethodEntry = true;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001934#if defined(WITH_JIT)
buzbee9f601a92011-02-11 17:48:20 -08001935 dvmJitCalleeSave(calleeSave);
Ben Chenga4973592010-03-31 11:59:18 -07001936 /* Initialize the state to kJitNot */
buzbee9f601a92011-02-11 17:48:20 -08001937 self->jitState = kJitNot;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001938#endif
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001939
1940 /*
1941 * Initialize working state.
1942 *
1943 * No need to initialize "retval".
1944 */
buzbee9f601a92011-02-11 17:48:20 -08001945 self->interpSave.method = method;
1946 self->interpSave.fp = (u4*) self->curFrame;
1947 self->interpSave.pc = method->insns;
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001948
1949 assert(!dvmIsNativeMethod(method));
1950
1951 /*
1952 * Make sure the class is ready to go. Shouldn't be possible to get
1953 * here otherwise.
1954 */
1955 if (method->clazz->status < CLASS_INITIALIZING ||
1956 method->clazz->status == CLASS_ERROR)
1957 {
1958 LOGE("ERROR: tried to execute code in unprepared class '%s' (%d)\n",
1959 method->clazz->descriptor, method->clazz->status);
1960 dvmDumpThread(self, false);
1961 dvmAbort();
1962 }
1963
buzbee9a3147c2011-03-02 15:43:48 -08001964 typedef void (*Interpreter)(Thread*);
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001965 Interpreter stdInterp;
1966 if (gDvm.executionMode == kExecutionModeInterpFast)
1967 stdInterp = dvmMterpStd;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001968#if defined(WITH_JIT)
1969 else if (gDvm.executionMode == kExecutionModeJit)
Ben Chengba4fc8b2009-06-01 13:00:29 -07001970 stdInterp = dvmMterpStd;
1971#endif
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001972 else
buzbee9a3147c2011-03-02 15:43:48 -08001973 stdInterp = dvmInterpretPortable;
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001974
buzbee9a3147c2011-03-02 15:43:48 -08001975 // Call the interpreter
1976 (*stdInterp)(self);
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001977
buzbee9f601a92011-02-11 17:48:20 -08001978 *pResult = self->retval;
1979
1980 /* Restore interpreter state from previous activation */
1981 self->interpSave = interpSaveState;
Bill Buzbee342806d2009-12-08 12:37:13 -08001982#if defined(WITH_JIT)
buzbee9f601a92011-02-11 17:48:20 -08001983 dvmJitCalleeRestore(calleeSave);
Bill Buzbee342806d2009-12-08 12:37:13 -08001984#endif
buzbee9a3147c2011-03-02 15:43:48 -08001985 if (savedBreakFlags | savedSubModes) {
1986 dvmUpdateInterpBreak(self, savedBreakFlags, savedSubModes,
1987 true /*enable*/);
1988 }
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001989}