blob: e670d49e841a6e11c8b6a6bf48eb72fd0d1b528b [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,
717 bool methodEntry, 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
730 if (methodEntry)
731 eventFlags |= DBG_METHOD_ENTRY;
732
733 /*
734 * See if we have a breakpoint here.
735 *
736 * Depending on the "mods" associated with event(s) on this address,
737 * we may or may not actually send a message to the debugger.
738 */
739 if (GET_OPCODE(*pc) == OP_BREAKPOINT) {
740 LOGV("+++ breakpoint hit at %p\n", pc);
741 eventFlags |= DBG_BREAKPOINT;
742 }
743
744 /*
745 * If the debugger is single-stepping one of our threads, check to
746 * see if we're that thread and we've reached a step point.
747 */
748 const StepControl* pCtrl = &gDvm.stepControl;
749 if (pCtrl->active && pCtrl->thread == self) {
750 int frameDepth;
751 bool doStop = false;
752 const char* msg = NULL;
753
754 assert(!dvmIsNativeMethod(method));
755
756 if (pCtrl->depth == SD_INTO) {
757 /*
758 * Step into method calls. We break when the line number
759 * or method pointer changes. If we're in SS_MIN mode, we
760 * always stop.
761 */
762 if (pCtrl->method != method) {
763 doStop = true;
764 msg = "new method";
765 } else if (pCtrl->size == SS_MIN) {
766 doStop = true;
767 msg = "new instruction";
768 } else if (!dvmAddressSetGet(
769 pCtrl->pAddressSet, pc - method->insns)) {
770 doStop = true;
771 msg = "new line";
772 }
773 } else if (pCtrl->depth == SD_OVER) {
774 /*
775 * Step over method calls. We break when the line number is
776 * different and the frame depth is <= the original frame
777 * depth. (We can't just compare on the method, because we
778 * might get unrolled past it by an exception, and it's tricky
779 * to identify recursion.)
780 */
781 frameDepth = dvmComputeVagueFrameDepth(self, fp);
782 if (frameDepth < pCtrl->frameDepth) {
783 /* popped up one or more frames, always trigger */
784 doStop = true;
785 msg = "method pop";
786 } else if (frameDepth == pCtrl->frameDepth) {
787 /* same depth, see if we moved */
788 if (pCtrl->size == SS_MIN) {
789 doStop = true;
790 msg = "new instruction";
791 } else if (!dvmAddressSetGet(pCtrl->pAddressSet,
792 pc - method->insns)) {
793 doStop = true;
794 msg = "new line";
795 }
796 }
797 } else {
798 assert(pCtrl->depth == SD_OUT);
799 /*
800 * Return from the current method. We break when the frame
801 * depth pops up.
802 *
803 * This differs from the "method exit" break in that it stops
804 * with the PC at the next instruction in the returned-to
805 * function, rather than the end of the returning function.
806 */
807 frameDepth = dvmComputeVagueFrameDepth(self, fp);
808 if (frameDepth < pCtrl->frameDepth) {
809 doStop = true;
810 msg = "method pop";
811 }
812 }
813
814 if (doStop) {
815 LOGV("#####S %s\n", msg);
816 eventFlags |= DBG_SINGLE_STEP;
817 }
818 }
819
820 /*
821 * Check to see if this is a "return" instruction. JDWP says we should
822 * send the event *after* the code has been executed, but it also says
823 * the location we provide is the last instruction. Since the "return"
824 * instruction has no interesting side effects, we should be safe.
825 * (We can't just move this down to the returnFromMethod label because
826 * we potentially need to combine it with other events.)
827 *
828 * We're also not supposed to generate a method exit event if the method
829 * terminates "with a thrown exception".
830 */
831 u2 opcode = GET_OPCODE(*pc);
832 if (opcode == OP_RETURN_VOID || opcode == OP_RETURN ||
833 opcode == OP_RETURN_WIDE ||opcode == OP_RETURN_OBJECT)
834 {
835 eventFlags |= DBG_METHOD_EXIT;
836 }
837
838 /*
839 * If there's something interesting going on, see if it matches one
840 * of the debugger filters.
841 */
842 if (eventFlags != 0) {
843 Object* thisPtr = dvmGetThisPtr(method, fp);
844 if (thisPtr != NULL && !dvmIsValidObject(thisPtr)) {
845 /*
846 * TODO: remove this check if we're confident that the "this"
847 * pointer is where it should be -- slows us down, especially
848 * during single-step.
849 */
850 char* desc = dexProtoCopyMethodDescriptor(&method->prototype);
851 LOGE("HEY: invalid 'this' ptr %p (%s.%s %s)\n", thisPtr,
852 method->clazz->descriptor, method->name, desc);
853 free(desc);
854 dvmAbort();
855 }
856 dvmDbgPostLocationEvent(method, pc - method->insns, thisPtr,
857 eventFlags);
858 }
859}
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700860
861/*
862 * Recover the "this" pointer from the current interpreted method. "this"
863 * is always in "in0" for non-static methods.
864 *
865 * The "ins" start at (#of registers - #of ins). Note in0 != v0.
866 *
867 * This works because "dx" guarantees that it will work. It's probably
868 * fairly common to have a virtual method that doesn't use its "this"
869 * pointer, in which case we're potentially wasting a register. However,
870 * the debugger doesn't treat "this" as just another argument. For
871 * example, events (such as breakpoints) can be enabled for specific
872 * values of "this". There is also a separate StackFrame.ThisObject call
873 * in JDWP that is expected to work for any non-native non-static method.
874 *
875 * Because we need it when setting up debugger event filters, we want to
876 * be able to do this quickly.
877 */
878Object* dvmGetThisPtr(const Method* method, const u4* fp)
879{
880 if (dvmIsStaticMethod(method))
881 return NULL;
882 return (Object*)fp[method->registersSize - method->insSize];
883}
884
885
886#if defined(WITH_TRACKREF_CHECKS)
887/*
888 * Verify that all internally-tracked references have been released. If
889 * they haven't, print them and abort the VM.
890 *
891 * "debugTrackedRefStart" indicates how many refs were on the list when
892 * we were first invoked.
893 */
894void dvmInterpCheckTrackedRefs(Thread* self, const Method* method,
895 int debugTrackedRefStart)
896{
897 if (dvmReferenceTableEntries(&self->internalLocalRefTable)
898 != (size_t) debugTrackedRefStart)
899 {
900 char* desc;
901 Object** top;
902 int count;
903
904 count = dvmReferenceTableEntries(&self->internalLocalRefTable);
905
906 LOGE("TRACK: unreleased internal reference (prev=%d total=%d)\n",
907 debugTrackedRefStart, count);
908 desc = dexProtoCopyMethodDescriptor(&method->prototype);
909 LOGE(" current method is %s.%s %s\n", method->clazz->descriptor,
910 method->name, desc);
911 free(desc);
912 top = self->internalLocalRefTable.table + debugTrackedRefStart;
913 while (top < self->internalLocalRefTable.nextEntry) {
914 LOGE(" %p (%s)\n",
915 *top,
916 ((*top)->clazz != NULL) ? (*top)->clazz->descriptor : "");
917 top++;
918 }
919 dvmDumpThread(self, false);
920
921 dvmAbort();
922 }
923 //LOGI("TRACK OK\n");
924}
925#endif
926
927
928#ifdef LOG_INSTR
929/*
930 * Dump the v-registers. Sent to the ILOG log tag.
931 */
932void dvmDumpRegs(const Method* method, const u4* framePtr, bool inOnly)
933{
934 int i, localCount;
935
936 localCount = method->registersSize - method->insSize;
937
938 LOG(LOG_VERBOSE, LOG_TAG"i", "Registers (fp=%p):\n", framePtr);
939 for (i = method->registersSize-1; i >= 0; i--) {
940 if (i >= localCount) {
941 LOG(LOG_VERBOSE, LOG_TAG"i", " v%-2d in%-2d : 0x%08x\n",
942 i, i-localCount, framePtr[i]);
943 } else {
944 if (inOnly) {
945 LOG(LOG_VERBOSE, LOG_TAG"i", " [...]\n");
946 break;
947 }
948 const char* name = "";
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700949#if 0 // "locals" structure has changed -- need to rewrite this
Elliott Hughes8afa9df2010-07-07 14:47:25 -0700950 int j;
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700951 DexFile* pDexFile = method->clazz->pDexFile;
952 const DexCode* pDexCode = dvmGetMethodCode(method);
953 int localsSize = dexGetLocalsSize(pDexFile, pDexCode);
954 const DexLocal* locals = dvmDexGetLocals(pDexFile, pDexCode);
955 for (j = 0; j < localsSize, j++) {
956 if (locals[j].registerNum == (u4) i) {
957 name = dvmDexStringStr(locals[j].pName);
958 break;
959 }
960 }
961#endif
962 LOG(LOG_VERBOSE, LOG_TAG"i", " v%-2d : 0x%08x %s\n",
963 i, framePtr[i], name);
964 }
965 }
966}
967#endif
968
969
970/*
971 * ===========================================================================
972 * Entry point and general support functions
973 * ===========================================================================
974 */
975
Ben Cheng38329f52009-07-07 14:19:20 -0700976/*
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700977 * Construct an s4 from two consecutive half-words of switch data.
978 * This needs to check endianness because the DEX optimizer only swaps
979 * half-words in instruction stream.
980 *
981 * "switchData" must be 32-bit aligned.
982 */
983#if __BYTE_ORDER == __LITTLE_ENDIAN
984static inline s4 s4FromSwitchData(const void* switchData) {
985 return *(s4*) switchData;
986}
987#else
988static inline s4 s4FromSwitchData(const void* switchData) {
989 u2* data = switchData;
990 return data[0] | (((s4) data[1]) << 16);
Jay Freeman (saurik)ffa5c292008-11-16 13:51:51 +0000991}
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700992#endif
993
994/*
995 * Find the matching case. Returns the offset to the handler instructions.
996 *
997 * Returns 3 if we don't find a match (it's the size of the packed-switch
998 * instruction).
999 */
1000s4 dvmInterpHandlePackedSwitch(const u2* switchData, s4 testVal)
1001{
1002 const int kInstrLen = 3;
1003 u2 size;
1004 s4 firstKey;
1005 const s4* entries;
1006
1007 /*
1008 * Packed switch data format:
1009 * ushort ident = 0x0100 magic value
1010 * ushort size number of entries in the table
1011 * int first_key first (and lowest) switch case value
1012 * int targets[size] branch targets, relative to switch opcode
1013 *
1014 * Total size is (4+size*2) 16-bit code units.
1015 */
1016 if (*switchData++ != kPackedSwitchSignature) {
1017 /* should have been caught by verifier */
Dan Bornsteind27f3cf2011-02-23 13:07:07 -08001018 dvmThrowInternalError("bad packed switch magic");
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001019 return kInstrLen;
1020 }
1021
1022 size = *switchData++;
1023 assert(size > 0);
1024
1025 firstKey = *switchData++;
1026 firstKey |= (*switchData++) << 16;
1027
1028 if (testVal < firstKey || testVal >= firstKey + size) {
1029 LOGVV("Value %d not found in switch (%d-%d)\n",
1030 testVal, firstKey, firstKey+size-1);
1031 return kInstrLen;
1032 }
1033
1034 /* The entries are guaranteed to be aligned on a 32-bit boundary;
1035 * we can treat them as a native int array.
1036 */
1037 entries = (const s4*) switchData;
1038 assert(((u4)entries & 0x3) == 0);
1039
1040 assert(testVal - firstKey >= 0 && testVal - firstKey < size);
1041 LOGVV("Value %d found in slot %d (goto 0x%02x)\n",
1042 testVal, testVal - firstKey,
1043 s4FromSwitchData(&entries[testVal - firstKey]));
1044 return s4FromSwitchData(&entries[testVal - firstKey]);
1045}
1046
1047/*
1048 * Find the matching case. Returns the offset to the handler instructions.
1049 *
1050 * Returns 3 if we don't find a match (it's the size of the sparse-switch
1051 * instruction).
1052 */
1053s4 dvmInterpHandleSparseSwitch(const u2* switchData, s4 testVal)
1054{
1055 const int kInstrLen = 3;
Carl Shapiroe3c01da2010-05-20 22:54:18 -07001056 u2 size;
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001057 const s4* keys;
1058 const s4* entries;
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001059
1060 /*
1061 * Sparse switch data format:
1062 * ushort ident = 0x0200 magic value
1063 * ushort size number of entries in the table; > 0
1064 * int keys[size] keys, sorted low-to-high; 32-bit aligned
1065 * int targets[size] branch targets, relative to switch opcode
1066 *
1067 * Total size is (2+size*4) 16-bit code units.
1068 */
1069
1070 if (*switchData++ != kSparseSwitchSignature) {
1071 /* should have been caught by verifier */
Dan Bornsteind27f3cf2011-02-23 13:07:07 -08001072 dvmThrowInternalError("bad sparse switch magic");
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001073 return kInstrLen;
1074 }
1075
1076 size = *switchData++;
1077 assert(size > 0);
Ben Cheng38329f52009-07-07 14:19:20 -07001078
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001079 /* The keys are guaranteed to be aligned on a 32-bit boundary;
1080 * we can treat them as a native int array.
1081 */
1082 keys = (const s4*) switchData;
1083 assert(((u4)keys & 0x3) == 0);
1084
1085 /* The entries are guaranteed to be aligned on a 32-bit boundary;
1086 * we can treat them as a native int array.
1087 */
1088 entries = keys + size;
1089 assert(((u4)entries & 0x3) == 0);
1090
1091 /*
Andy McFadden62f19152009-10-21 16:59:31 -07001092 * Binary-search through the array of keys, which are guaranteed to
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001093 * be sorted low-to-high.
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001094 */
Andy McFadden62f19152009-10-21 16:59:31 -07001095 int lo = 0;
1096 int hi = size - 1;
1097 while (lo <= hi) {
1098 int mid = (lo + hi) >> 1;
1099
1100 s4 foundVal = s4FromSwitchData(&keys[mid]);
1101 if (testVal < foundVal) {
1102 hi = mid - 1;
1103 } else if (testVal > foundVal) {
1104 lo = mid + 1;
1105 } else {
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001106 LOGVV("Value %d found in entry %d (goto 0x%02x)\n",
Andy McFadden62f19152009-10-21 16:59:31 -07001107 testVal, mid, s4FromSwitchData(&entries[mid]));
1108 return s4FromSwitchData(&entries[mid]);
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001109 }
1110 }
1111
1112 LOGVV("Value %d not found in switch\n", testVal);
1113 return kInstrLen;
1114}
1115
1116/*
Andy McFadden6f214502009-06-30 16:14:30 -07001117 * Copy data for a fill-array-data instruction. On a little-endian machine
1118 * we can just do a memcpy(), on a big-endian system we have work to do.
1119 *
1120 * The trick here is that dexopt has byte-swapped each code unit, which is
1121 * exactly what we want for short/char data. For byte data we need to undo
1122 * the swap, and for 4- or 8-byte values we need to swap pieces within
1123 * each word.
1124 */
1125static void copySwappedArrayData(void* dest, const u2* src, u4 size, u2 width)
1126{
1127#if __BYTE_ORDER == __LITTLE_ENDIAN
1128 memcpy(dest, src, size*width);
1129#else
1130 int i;
1131
1132 switch (width) {
1133 case 1:
1134 /* un-swap pairs of bytes as we go */
1135 for (i = (size-1) & ~1; i >= 0; i -= 2) {
1136 ((u1*)dest)[i] = ((u1*)src)[i+1];
1137 ((u1*)dest)[i+1] = ((u1*)src)[i];
1138 }
1139 /*
1140 * "src" is padded to end on a two-byte boundary, but we don't want to
1141 * assume "dest" is, so we handle odd length specially.
1142 */
1143 if ((size & 1) != 0) {
1144 ((u1*)dest)[size-1] = ((u1*)src)[size];
1145 }
1146 break;
1147 case 2:
1148 /* already swapped correctly */
1149 memcpy(dest, src, size*width);
1150 break;
1151 case 4:
1152 /* swap word halves */
1153 for (i = 0; i < (int) size; i++) {
1154 ((u4*)dest)[i] = (src[(i << 1) + 1] << 16) | src[i << 1];
1155 }
1156 break;
1157 case 8:
1158 /* swap word halves and words */
1159 for (i = 0; i < (int) (size << 1); i += 2) {
1160 ((int*)dest)[i] = (src[(i << 1) + 3] << 16) | src[(i << 1) + 2];
1161 ((int*)dest)[i+1] = (src[(i << 1) + 1] << 16) | src[i << 1];
1162 }
1163 break;
1164 default:
1165 LOGE("Unexpected width %d in copySwappedArrayData\n", width);
1166 dvmAbort();
1167 break;
1168 }
1169#endif
1170}
1171
1172/*
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001173 * Fill the array with predefined constant values.
1174 *
1175 * Returns true if job is completed, otherwise false to indicate that
1176 * an exception has been thrown.
1177 */
The Android Open Source Project89c1feb2008-12-17 18:03:55 -08001178bool dvmInterpHandleFillArrayData(ArrayObject* arrayObj, const u2* arrayData)
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001179{
1180 u2 width;
1181 u4 size;
1182
The Android Open Source Project89c1feb2008-12-17 18:03:55 -08001183 if (arrayObj == NULL) {
Dan Bornsteind27f3cf2011-02-23 13:07:07 -08001184 dvmThrowNullPointerException(NULL);
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001185 return false;
1186 }
Barry Hayes7dc96602010-02-24 09:19:07 -08001187 assert (!IS_CLASS_FLAG_SET(((Object *)arrayObj)->clazz,
1188 CLASS_ISOBJECTARRAY));
The Android Open Source Project89c1feb2008-12-17 18:03:55 -08001189
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001190 /*
1191 * Array data table format:
1192 * ushort ident = 0x0300 magic value
1193 * ushort width width of each element in the table
1194 * uint size number of elements in the table
1195 * ubyte data[size*width] table of data values (may contain a single-byte
1196 * padding at the end)
1197 *
1198 * Total size is 4+(width * size + 1)/2 16-bit code units.
1199 */
1200 if (arrayData[0] != kArrayDataSignature) {
Dan Bornsteind27f3cf2011-02-23 13:07:07 -08001201 dvmThrowInternalError("bad array data magic");
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001202 return false;
1203 }
1204
1205 width = arrayData[1];
1206 size = arrayData[2] | (((u4)arrayData[3]) << 16);
1207
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001208 if (size > arrayObj->length) {
Dan Bornstein47f58252011-03-07 14:54:14 -08001209 dvmThrowArrayIndexOutOfBoundsException(arrayObj->length, size);
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001210 return false;
1211 }
Andy McFadden6f214502009-06-30 16:14:30 -07001212 copySwappedArrayData(arrayObj->contents, &arrayData[4], size, width);
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001213 return true;
1214}
1215
1216/*
1217 * Find the concrete method that corresponds to "methodIdx". The code in
1218 * "method" is executing invoke-method with "thisClass" as its first argument.
1219 *
1220 * Returns NULL with an exception raised on failure.
1221 */
1222Method* dvmInterpFindInterfaceMethod(ClassObject* thisClass, u4 methodIdx,
1223 const Method* method, DvmDex* methodClassDex)
1224{
1225 Method* absMethod;
1226 Method* methodToCall;
1227 int i, vtableIndex;
1228
1229 /*
1230 * Resolve the method. This gives us the abstract method from the
1231 * interface class declaration.
1232 */
1233 absMethod = dvmDexGetResolvedMethod(methodClassDex, methodIdx);
1234 if (absMethod == NULL) {
1235 absMethod = dvmResolveInterfaceMethod(method->clazz, methodIdx);
1236 if (absMethod == NULL) {
1237 LOGV("+ unknown method\n");
1238 return NULL;
1239 }
1240 }
1241
1242 /* make sure absMethod->methodIndex means what we think it means */
1243 assert(dvmIsAbstractMethod(absMethod));
1244
1245 /*
1246 * Run through the "this" object's iftable. Find the entry for
1247 * absMethod's class, then use absMethod->methodIndex to find
1248 * the method's entry. The value there is the offset into our
1249 * vtable of the actual method to execute.
1250 *
1251 * The verifier does not guarantee that objects stored into
1252 * interface references actually implement the interface, so this
1253 * check cannot be eliminated.
1254 */
1255 for (i = 0; i < thisClass->iftableCount; i++) {
1256 if (thisClass->iftable[i].clazz == absMethod->clazz)
1257 break;
1258 }
1259 if (i == thisClass->iftableCount) {
1260 /* impossible in verified DEX, need to check for it in unverified */
Dan Bornstein70b00ab2011-02-23 14:11:27 -08001261 dvmThrowIncompatibleClassChangeError("interface not implemented");
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001262 return NULL;
1263 }
1264
1265 assert(absMethod->methodIndex <
1266 thisClass->iftable[i].clazz->virtualMethodCount);
1267
1268 vtableIndex =
1269 thisClass->iftable[i].methodIndexArray[absMethod->methodIndex];
1270 assert(vtableIndex >= 0 && vtableIndex < thisClass->vtableCount);
1271 methodToCall = thisClass->vtable[vtableIndex];
1272
1273#if 0
1274 /* this can happen when there's a stale class file */
1275 if (dvmIsAbstractMethod(methodToCall)) {
Dan Bornsteind27f3cf2011-02-23 13:07:07 -08001276 dvmThrowAbstractMethodError("interface method not implemented");
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001277 return NULL;
1278 }
1279#else
1280 assert(!dvmIsAbstractMethod(methodToCall) ||
1281 methodToCall->nativeFunc != NULL);
1282#endif
1283
1284 LOGVV("+++ interface=%s.%s concrete=%s.%s\n",
1285 absMethod->clazz->descriptor, absMethod->name,
1286 methodToCall->clazz->descriptor, methodToCall->name);
1287 assert(methodToCall != NULL);
1288
1289 return methodToCall;
1290}
1291
1292
Andy McFaddenb51ea112009-05-08 16:50:17 -07001293
1294/*
1295 * Helpers for dvmThrowVerificationError().
1296 *
1297 * Each returns a newly-allocated string.
1298 */
1299#define kThrowShow_accessFromClass 1
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001300static char* classNameFromIndex(const Method* method, int ref,
1301 VerifyErrorRefType refType, int flags)
Andy McFaddenb51ea112009-05-08 16:50:17 -07001302{
1303 static const int kBufLen = 256;
1304 const DvmDex* pDvmDex = method->clazz->pDvmDex;
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001305
1306 if (refType == VERIFY_ERROR_REF_FIELD) {
1307 /* get class ID from field ID */
1308 const DexFieldId* pFieldId = dexGetFieldId(pDvmDex->pDexFile, ref);
1309 ref = pFieldId->classIdx;
1310 } else if (refType == VERIFY_ERROR_REF_METHOD) {
1311 /* get class ID from method ID */
1312 const DexMethodId* pMethodId = dexGetMethodId(pDvmDex->pDexFile, ref);
1313 ref = pMethodId->classIdx;
1314 }
1315
Andy McFaddenb51ea112009-05-08 16:50:17 -07001316 const char* className = dexStringByTypeIdx(pDvmDex->pDexFile, ref);
Elliott Hughes50169662010-11-22 13:14:23 -08001317 char* dotClassName = dvmHumanReadableDescriptor(className);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001318 if (flags == 0)
1319 return dotClassName;
1320
1321 char* result = (char*) malloc(kBufLen);
1322
1323 if ((flags & kThrowShow_accessFromClass) != 0) {
Elliott Hughes50169662010-11-22 13:14:23 -08001324 char* dotFromName =
1325 dvmHumanReadableDescriptor(method->clazz->descriptor);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001326 snprintf(result, kBufLen, "tried to access class %s from class %s",
1327 dotClassName, dotFromName);
1328 free(dotFromName);
1329 } else {
1330 assert(false); // should've been caught above
1331 result[0] = '\0';
1332 }
1333
1334 free(dotClassName);
1335 return result;
1336}
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001337static char* fieldNameFromIndex(const Method* method, int ref,
1338 VerifyErrorRefType refType, int flags)
Andy McFaddenb51ea112009-05-08 16:50:17 -07001339{
1340 static const int kBufLen = 256;
1341 const DvmDex* pDvmDex = method->clazz->pDvmDex;
1342 const DexFieldId* pFieldId;
1343 const char* className;
1344 const char* fieldName;
1345
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001346 if (refType != VERIFY_ERROR_REF_FIELD) {
1347 LOGW("Expected ref type %d, got %d\n", VERIFY_ERROR_REF_FIELD, refType);
1348 return NULL; /* no message */
1349 }
1350
Andy McFaddenb51ea112009-05-08 16:50:17 -07001351 pFieldId = dexGetFieldId(pDvmDex->pDexFile, ref);
1352 className = dexStringByTypeIdx(pDvmDex->pDexFile, pFieldId->classIdx);
1353 fieldName = dexStringById(pDvmDex->pDexFile, pFieldId->nameIdx);
1354
Elliott Hughes50169662010-11-22 13:14:23 -08001355 char* dotName = dvmHumanReadableDescriptor(className);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001356 char* result = (char*) malloc(kBufLen);
1357
1358 if ((flags & kThrowShow_accessFromClass) != 0) {
Elliott Hughes50169662010-11-22 13:14:23 -08001359 char* dotFromName =
1360 dvmHumanReadableDescriptor(method->clazz->descriptor);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001361 snprintf(result, kBufLen, "tried to access field %s.%s from class %s",
1362 dotName, fieldName, dotFromName);
1363 free(dotFromName);
1364 } else {
1365 snprintf(result, kBufLen, "%s.%s", dotName, fieldName);
1366 }
1367
1368 free(dotName);
1369 return result;
1370}
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001371static char* methodNameFromIndex(const Method* method, int ref,
1372 VerifyErrorRefType refType, int flags)
Andy McFaddenb51ea112009-05-08 16:50:17 -07001373{
1374 static const int kBufLen = 384;
1375 const DvmDex* pDvmDex = method->clazz->pDvmDex;
1376 const DexMethodId* pMethodId;
1377 const char* className;
1378 const char* methodName;
1379
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001380 if (refType != VERIFY_ERROR_REF_METHOD) {
1381 LOGW("Expected ref type %d, got %d\n", VERIFY_ERROR_REF_METHOD,refType);
1382 return NULL; /* no message */
1383 }
1384
Andy McFaddenb51ea112009-05-08 16:50:17 -07001385 pMethodId = dexGetMethodId(pDvmDex->pDexFile, ref);
1386 className = dexStringByTypeIdx(pDvmDex->pDexFile, pMethodId->classIdx);
1387 methodName = dexStringById(pDvmDex->pDexFile, pMethodId->nameIdx);
1388
Elliott Hughes50169662010-11-22 13:14:23 -08001389 char* dotName = dvmHumanReadableDescriptor(className);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001390 char* result = (char*) malloc(kBufLen);
1391
1392 if ((flags & kThrowShow_accessFromClass) != 0) {
Elliott Hughes50169662010-11-22 13:14:23 -08001393 char* dotFromName =
1394 dvmHumanReadableDescriptor(method->clazz->descriptor);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001395 char* desc = dexProtoCopyMethodDescriptor(&method->prototype);
1396 snprintf(result, kBufLen,
1397 "tried to access method %s.%s:%s from class %s",
1398 dotName, methodName, desc, dotFromName);
1399 free(dotFromName);
1400 free(desc);
1401 } else {
1402 snprintf(result, kBufLen, "%s.%s", dotName, methodName);
1403 }
1404
1405 free(dotName);
1406 return result;
1407}
1408
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001409/*
Andy McFadden3a1aedb2009-05-07 13:30:23 -07001410 * Throw an exception for a problem identified by the verifier.
1411 *
1412 * This is used by the invoke-verification-error instruction. It always
1413 * throws an exception.
1414 *
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001415 * "kind" indicates the kind of failure encountered by the verifier. It
1416 * has two parts, an error code and an indication of the reference type.
Andy McFadden3a1aedb2009-05-07 13:30:23 -07001417 */
Andy McFaddenb51ea112009-05-08 16:50:17 -07001418void dvmThrowVerificationError(const Method* method, int kind, int ref)
Andy McFadden3a1aedb2009-05-07 13:30:23 -07001419{
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001420 const int typeMask = 0xff << kVerifyErrorRefTypeShift;
1421 VerifyError errorKind = kind & ~typeMask;
1422 VerifyErrorRefType refType = kind >> kVerifyErrorRefTypeShift;
Dan Bornsteina3b35122011-03-03 16:17:37 -08001423 ClassObject* exceptionClass = gDvm.exVerifyError;
Andy McFaddenb51ea112009-05-08 16:50:17 -07001424 char* msg = NULL;
1425
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001426 switch ((VerifyError) errorKind) {
Andy McFaddenb51ea112009-05-08 16:50:17 -07001427 case VERIFY_ERROR_NO_CLASS:
Dan Bornsteina3b35122011-03-03 16:17:37 -08001428 exceptionClass = gDvm.exNoClassDefFoundError;
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001429 msg = classNameFromIndex(method, ref, refType, 0);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001430 break;
1431 case VERIFY_ERROR_NO_FIELD:
Dan Bornsteina3b35122011-03-03 16:17:37 -08001432 exceptionClass = gDvm.exNoSuchFieldError;
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001433 msg = fieldNameFromIndex(method, ref, refType, 0);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001434 break;
1435 case VERIFY_ERROR_NO_METHOD:
Dan Bornsteina3b35122011-03-03 16:17:37 -08001436 exceptionClass = gDvm.exNoSuchMethodError;
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001437 msg = methodNameFromIndex(method, ref, refType, 0);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001438 break;
1439 case VERIFY_ERROR_ACCESS_CLASS:
Dan Bornsteina3b35122011-03-03 16:17:37 -08001440 exceptionClass = gDvm.exIllegalAccessError;
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001441 msg = classNameFromIndex(method, ref, refType,
1442 kThrowShow_accessFromClass);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001443 break;
1444 case VERIFY_ERROR_ACCESS_FIELD:
Dan Bornsteina3b35122011-03-03 16:17:37 -08001445 exceptionClass = gDvm.exIllegalAccessError;
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001446 msg = fieldNameFromIndex(method, ref, refType,
1447 kThrowShow_accessFromClass);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001448 break;
1449 case VERIFY_ERROR_ACCESS_METHOD:
Dan Bornsteina3b35122011-03-03 16:17:37 -08001450 exceptionClass = gDvm.exIllegalAccessError;
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001451 msg = methodNameFromIndex(method, ref, refType,
1452 kThrowShow_accessFromClass);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001453 break;
1454 case VERIFY_ERROR_CLASS_CHANGE:
Dan Bornsteina3b35122011-03-03 16:17:37 -08001455 exceptionClass = gDvm.exIncompatibleClassChangeError;
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001456 msg = classNameFromIndex(method, ref, refType, 0);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001457 break;
1458 case VERIFY_ERROR_INSTANTIATION:
Dan Bornsteina3b35122011-03-03 16:17:37 -08001459 exceptionClass = gDvm.exInstantiationError;
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001460 msg = classNameFromIndex(method, ref, refType, 0);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001461 break;
1462
1463 case VERIFY_ERROR_GENERIC:
1464 /* generic VerifyError; use default exception, no message */
1465 break;
1466 case VERIFY_ERROR_NONE:
1467 /* should never happen; use default exception */
1468 assert(false);
1469 msg = strdup("weird - no error specified");
1470 break;
1471
1472 /* no default clause -- want warning if enum updated */
1473 }
1474
Dan Bornstein0b8b2932011-03-04 11:53:40 -08001475 dvmThrowException(exceptionClass, msg);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001476 free(msg);
Andy McFadden3a1aedb2009-05-07 13:30:23 -07001477}
1478
Andy McFadden3a1aedb2009-05-07 13:30:23 -07001479/*
buzbee9a3147c2011-03-02 15:43:48 -08001480 * Update interpBreak. If there is an active break when
1481 * we're done, set altHandlerTable. Otherwise, revert to
1482 * the non-breaking table base.
buzbeecb3081f2011-01-14 13:37:31 -08001483 */
buzbee9a3147c2011-03-02 15:43:48 -08001484void dvmUpdateInterpBreak(Thread* thread, int newBreak, int newMode,
1485 bool enable)
buzbeecb3081f2011-01-14 13:37:31 -08001486{
buzbee9a3147c2011-03-02 15:43:48 -08001487 InterpBreak oldValue, newValue;
1488
1489 // Do not use this routine for suspend updates. See below.
1490 assert((newBreak & kInterpSuspendBreak) == 0);
buzbeecb3081f2011-01-14 13:37:31 -08001491
1492 do {
buzbee9a3147c2011-03-02 15:43:48 -08001493 oldValue = newValue = thread->interpBreak;
1494 if (enable) {
1495 newValue.ctl.breakFlags |= newBreak;
1496 newValue.ctl.subMode |= newMode;
1497 } else {
1498 newValue.ctl.breakFlags &= ~newBreak;
1499 newValue.ctl.subMode &= ~newMode;
1500 }
1501 newValue.ctl.curHandlerTable = (newValue.ctl.breakFlags) ?
1502 thread->altHandlerTable : thread->mainHandlerTable;
1503 } while (dvmQuasiAtomicCas64(oldValue.all, newValue.all,
1504 &thread->interpBreak.all) != 0);
1505}
1506
1507/*
1508 * Update the normal and debugger suspend counts for a thread.
1509 * threadSuspendCount must be acquired before calling this to
1510 * ensure a clean update of suspendCount, dbgSuspendCount and
1511 * sumThreadSuspendCount. suspendCount & dbgSuspendCount must
1512 * use the atomic update to avoid conflict with writes to the
1513 * other fields in interpBreak.
1514 *
1515 * CLEANUP TODO: Currently only the JIT is using sumThreadSuspendCount.
1516 * Move under WITH_JIT ifdefs.
1517*/
1518void dvmAddToSuspendCounts(Thread* thread, int delta, int dbgDelta)
1519{
1520 InterpBreak oldValue, newValue;
1521
1522 do {
1523 oldValue = newValue = thread->interpBreak;
1524 newValue.ctl.suspendCount += delta;
1525 newValue.ctl.dbgSuspendCount += dbgDelta;
1526 assert(newValue.ctl.suspendCount >= newValue.ctl.dbgSuspendCount);
1527 if (newValue.ctl.suspendCount > 0) {
1528 newValue.ctl.breakFlags |= kInterpSuspendBreak;
1529 } else {
1530 newValue.ctl.breakFlags &= ~kInterpSuspendBreak;
1531 }
1532 newValue.ctl.curHandlerTable = (newValue.ctl.breakFlags) ?
1533 thread->altHandlerTable : thread->mainHandlerTable;
1534 } while (dvmQuasiAtomicCas64(oldValue.all, newValue.all,
1535 &thread->interpBreak.all) != 0);
1536
1537 // Update the global suspend count total
1538 gDvm.sumThreadSuspendCount += delta;
1539}
1540
1541/*
1542 * Update interpBreak for all threads.
1543 */
1544void dvmUpdateAllInterpBreak(int newBreak, int newMode, bool enable)
1545{
1546 Thread* self = dvmThreadSelf();
1547 Thread* thread;
1548
1549 dvmLockThreadList(self);
1550 for (thread = gDvm.threadList; thread != NULL; thread = thread->next) {
1551 dvmUpdateInterpBreak(thread, newBreak, newMode, enable);
1552 }
1553 dvmUnlockThreadList();
buzbeecb3081f2011-01-14 13:37:31 -08001554}
1555
1556/*
buzbee99e3e6e2011-03-29 10:26:07 -07001557 * Do a sanity check on interpreter state saved to Thread.
1558 * A failure here doesn't necessarily mean that something is wrong,
1559 * so this code should only be used during development to suggest
1560 * a possible problem.
1561 */
1562void dvmCheckInterpStateConsistency()
1563{
1564 Thread* self = dvmThreadSelf();
1565 Thread* thread;
1566 uint8_t breakFlags;
1567 uint8_t subMode;
1568 void* handlerTable;
1569
1570 dvmLockThreadList(self);
1571 breakFlags = self->interpBreak.ctl.breakFlags;
1572 subMode = self->interpBreak.ctl.subMode;
1573 handlerTable = self->interpBreak.ctl.curHandlerTable;
1574 for (thread = gDvm.threadList; thread != NULL; thread = thread->next) {
1575 if (subMode != thread->interpBreak.ctl.subMode) {
1576 LOGD("Warning: subMode mismatch - 0x%x:0x%x, tid[%d]",
1577 subMode,thread->interpBreak.ctl.subMode,thread->threadId);
1578 }
1579 if (breakFlags != thread->interpBreak.ctl.breakFlags) {
1580 LOGD("Warning: breakFlags mismatch - 0x%x:0x%x, tid[%d]",
1581 breakFlags,thread->interpBreak.ctl.breakFlags,thread->threadId);
1582 }
1583 if (handlerTable != thread->interpBreak.ctl.curHandlerTable) {
1584 LOGD("Warning: curHandlerTable mismatch - 0x%x:0x%x, tid[%d]",
1585 (int)handlerTable,(int)thread->interpBreak.ctl.curHandlerTable,
1586 thread->threadId);
1587 }
1588#if defined(WITH_JIT)
1589 if (thread->pJitProfTable != gDvmJit.pProfTable) {
1590 LOGD("Warning: pJitProfTable mismatch - 0x%x:0x%x, tid[%d]",
1591 (int)thread->pJitProfTable,(int)gDvmJit.pProfTable,
1592 thread->threadId);
1593 }
1594 if (thread->jitThreshold != gDvmJit.threshold) {
1595 LOGD("Warning: jitThreshold mismatch - 0x%x:0x%x, tid[%d]",
1596 (int)thread->jitThreshold,(int)gDvmJit.threshold,
1597 thread->threadId);
1598 }
1599#endif
1600 }
1601 dvmUnlockThreadList();
1602}
1603
1604/*
buzbee94d65252011-03-24 16:41:03 -07001605 * Arm a safepoint callback for a thread. If funct is null,
1606 * clear any pending callback.
1607 * TODO: only gc is currently using this feature, and will have
1608 * at most a single outstanding callback request. Until we need
1609 * something more capable and flexible, enforce this limit.
1610 */
1611void dvmArmSafePointCallback(Thread* thread, SafePointCallback funct,
1612 void* arg)
1613{
1614 dvmLockMutex(&thread->callbackMutex);
1615 if ((funct == NULL) || (thread->callback == NULL)) {
1616 thread->callback = funct;
1617 thread->callbackArg = arg;
1618 dvmUpdateInterpBreak(thread, kInterpSafePointCallback,
1619 kSubModeNormal, (funct != NULL));
1620 } else {
1621 // Already armed. Different?
1622 if ((funct != thread->callback) ||
1623 (arg != thread->callbackArg)) {
1624 // Yes - report failure and die
1625 LOGE("ArmSafePointCallback failed, thread %d", thread->threadId);
1626 dvmUnlockMutex(&thread->callbackMutex);
1627 dvmAbort();
1628 }
1629 }
1630 dvmUnlockMutex(&thread->callbackMutex);
1631}
1632
1633/*
buzbee9f601a92011-02-11 17:48:20 -08001634 * One-time initialization at thread creation. Here we initialize
1635 * useful constants.
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001636 */
buzbee9f601a92011-02-11 17:48:20 -08001637void dvmInitInterpreterState(Thread* self)
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001638{
Ben Chengba4fc8b2009-06-01 13:00:29 -07001639#if defined(WITH_JIT)
1640 /* Interpreter entry points from compiled code */
1641 extern void dvmJitToInterpNormal();
1642 extern void dvmJitToInterpNoChain();
1643 extern void dvmJitToInterpPunt();
1644 extern void dvmJitToInterpSingleStep();
Ben Cheng40094c12010-02-24 20:58:44 -08001645 extern void dvmJitToInterpTraceSelect();
Jeff Hao97319a82009-08-12 16:57:15 -07001646#if defined(WITH_SELF_VERIFICATION)
Ben Cheng40094c12010-02-24 20:58:44 -08001647 extern void dvmJitToInterpBackwardBranch();
Jeff Hao97319a82009-08-12 16:57:15 -07001648#endif
Ben Cheng38329f52009-07-07 14:19:20 -07001649 /*
Ben Chengba4fc8b2009-06-01 13:00:29 -07001650 * Reserve a static entity here to quickly setup runtime contents as
1651 * gcc will issue block copy instructions.
1652 */
1653 static struct JitToInterpEntries jitToInterpEntries = {
1654 dvmJitToInterpNormal,
1655 dvmJitToInterpNoChain,
1656 dvmJitToInterpPunt,
1657 dvmJitToInterpSingleStep,
Ben Cheng40094c12010-02-24 20:58:44 -08001658 dvmJitToInterpTraceSelect,
Jeff Hao97319a82009-08-12 16:57:15 -07001659#if defined(WITH_SELF_VERIFICATION)
Ben Cheng40094c12010-02-24 20:58:44 -08001660 dvmJitToInterpBackwardBranch,
buzbee9f601a92011-02-11 17:48:20 -08001661#else
1662 NULL,
Jeff Hao97319a82009-08-12 16:57:15 -07001663#endif
Ben Chengba4fc8b2009-06-01 13:00:29 -07001664 };
buzbee9f601a92011-02-11 17:48:20 -08001665#endif
Ben Cheng7a0bcd02010-01-22 16:45:45 -08001666
buzbee9f601a92011-02-11 17:48:20 -08001667 // Begin initialization
1668 self->cardTable = gDvm.biasedCardTableBase;
buzbee9f601a92011-02-11 17:48:20 -08001669#if defined(WITH_JIT)
buzbee9a3147c2011-03-02 15:43:48 -08001670 // One-time initializations
buzbee9f601a92011-02-11 17:48:20 -08001671 self->jitToInterpEntries = jitToInterpEntries;
1672 self->icRechainCount = PREDICTED_CHAIN_COUNTER_RECHAIN;
buzbee9f601a92011-02-11 17:48:20 -08001673 self->pProfileCountdown = &gDvmJit.profileCountdown;
buzbee9a3147c2011-03-02 15:43:48 -08001674 // Jit state that can change
buzbee99e3e6e2011-03-29 10:26:07 -07001675 dvmJitUpdateThreadStateSingle(self);
buzbee9f601a92011-02-11 17:48:20 -08001676#endif
buzbee99e3e6e2011-03-29 10:26:07 -07001677}
buzbee9f601a92011-02-11 17:48:20 -08001678
buzbee99e3e6e2011-03-29 10:26:07 -07001679/*
1680 * For a newly-created thread, we need to start off with interpBreak
1681 * set to any existing global modes. The caller must hold the
1682 * thread list lock.
1683 */
1684void dvmInitializeInterpBreak(Thread* thread)
1685{
1686 u1 flags = 0;
1687 u1 subModes = 0;
1688
1689 if (gDvm.instructionCountEnableCount > 0) {
1690 flags |= kInterpInstCountBreak;
1691 subModes |= kSubModeInstCounting;
1692 }
1693 if (dvmIsMethodTraceActive()) {
1694 subModes |= kSubModeMethodTrace;
1695 }
1696 if (gDvm.debuggerActive) {
1697 flags |= kInterpDebugBreak;
1698 subModes |= kSubModeDebuggerActive;
1699 }
1700 dvmUpdateInterpBreak(thread, flags, subModes, true);
buzbee9f601a92011-02-11 17:48:20 -08001701}
1702
buzbeea7d59bb2011-02-24 09:38:17 -08001703/*
1704 * Inter-instruction handler invoked in between instruction interpretations
1705 * to handle exceptional events such as debugging housekeeping, instruction
buzbee9a3147c2011-03-02 15:43:48 -08001706 * count profiling, JIT trace building, etc. Dalvik PC has been exported
1707 * prior to call, but Thread copy of dPC & fp are not current.
buzbeea7d59bb2011-02-24 09:38:17 -08001708 */
buzbee94d65252011-03-24 16:41:03 -07001709void dvmCheckBefore(const u2 *pc, u4 *fp, Thread* self)
buzbeea7d59bb2011-02-24 09:38:17 -08001710{
buzbee9a3147c2011-03-02 15:43:48 -08001711 const Method* method = self->interpSave.method;
1712 assert(self->interpBreak.ctl.breakFlags != 0);
1713 assert(pc >= method->insns && pc <
1714 method->insns + dvmGetMethodInsnsSize(method));
1715
1716#if 0
1717 /*
1718 * When we hit a specific method, enable verbose instruction logging.
1719 * Sometimes it's helpful to use the debugger attach as a trigger too.
1720 */
1721 if (*pIsMethodEntry) {
1722 static const char* cd = "Landroid/test/Arithmetic;";
1723 static const char* mn = "shiftTest2";
1724 static const char* sg = "()V";
1725
1726 if (/*self->interpBreak.ctl.subMode & kSubModeDebuggerActive &&*/
1727 strcmp(method->clazz->descriptor, cd) == 0 &&
1728 strcmp(method->name, mn) == 0 &&
1729 strcmp(method->shorty, sg) == 0)
1730 {
1731 LOGW("Reached %s.%s, enabling verbose mode\n",
1732 method->clazz->descriptor, method->name);
1733 android_setMinPriority(LOG_TAG"i", ANDROID_LOG_VERBOSE);
1734 dumpRegs(method, fp, true);
1735 }
1736
1737 if (!gDvm.debuggerActive)
1738 *pIsMethodEntry = false;
1739 }
1740#endif
1741
buzbee94d65252011-03-24 16:41:03 -07001742 /* Safe point handling */
1743 if (self->interpBreak.ctl.suspendCount ||
1744 (self->interpBreak.ctl.breakFlags & kInterpSafePointCallback)) {
buzbeec4a8caf2011-03-24 12:56:41 -07001745 // Are we are a safe point?
1746 int flags;
1747 flags = dexGetFlagsFromOpcode(dexOpcodeFromCodeUnit(*pc));
1748 if (flags & VERIFY_GC_INST_MASK) {
buzbee94d65252011-03-24 16:41:03 -07001749 // Yes, at a safe point. Pending callback?
1750 if (self->interpBreak.ctl.breakFlags & kInterpSafePointCallback) {
1751 SafePointCallback callback;
1752 void* arg;
1753 // Get consistent funct/arg pair
1754 dvmLockMutex(&self->callbackMutex);
1755 callback = self->callback;
1756 arg = self->callbackArg;
1757 dvmUnlockMutex(&self->callbackMutex);
1758 // Update Thread structure
1759 self->interpSave.pc = pc;
1760 self->interpSave.fp = fp;
1761 if (callback != NULL) {
1762 // Do the callback
1763 if (!callback(self,arg)) {
1764 // disarm
1765 dvmArmSafePointCallback(self, NULL, NULL);
1766 }
1767 }
1768 }
1769 // Need to suspend?
1770 if (self->interpBreak.ctl.suspendCount) {
1771 dvmExportPC(pc, fp);
1772 dvmCheckSuspendPending(self);
1773 }
buzbeec4a8caf2011-03-24 12:56:41 -07001774 }
buzbee9a3147c2011-03-02 15:43:48 -08001775 }
1776
1777 if (self->interpBreak.ctl.subMode & kSubModeDebuggerActive) {
buzbee99e3e6e2011-03-29 10:26:07 -07001778 updateDebugger(method, pc, fp,
1779 self->debugIsMethodEntry, self);
buzbee9a3147c2011-03-02 15:43:48 -08001780 }
1781 if (gDvm.instructionCountEnableCount != 0) {
1782 /*
1783 * Count up the #of executed instructions. This isn't synchronized
1784 * for thread-safety; if we need that we should make this
1785 * thread-local and merge counts into the global area when threads
1786 * exit (perhaps suspending all other threads GC-style and pulling
1787 * the data out of them).
1788 */
1789 gDvm.executedInstrCounts[GET_OPCODE(*pc)]++;
1790 }
1791
1792
1793#if defined(WITH_TRACKREF_CHECKS)
1794 dvmInterpCheckTrackedRefs(self, method,
1795 self->interpSave.debugTrackedRefStart);
1796#endif
1797
1798#if defined(WITH_JIT)
1799 // Does the JIT need anything done now?
1800 if (self->interpBreak.ctl.breakFlags & kInterpJitBreak) {
1801 // Are we building a trace?
1802 if (self->interpBreak.ctl.subMode & kSubModeJitTraceBuild) {
1803 dvmCheckJit(pc, self);
1804 }
1805
1806#if defined(WITH_SELF_VERIFICATION)
1807 // Are we replaying a trace?
1808 if (self->interpBreak.ctl.subMode & kSubModeJitSV) {
1809 dvmCheckSelfVerification(pc, self);
1810 }
1811#endif
1812 }
1813#endif
1814
1815 /*
1816 * SingleStep processing. NOTE: must be the last here to allow
1817 * preceeding special case handler to manipulate single-step count.
1818 */
1819 if (self->interpBreak.ctl.breakFlags & kInterpSingleStep) {
1820 if (self->singleStepCount == 0) {
1821 // We've exhausted our single step count
1822 dvmUpdateInterpBreak(self, kInterpSingleStep, kSubModeNormal,
1823 false /* remove */);
1824#if defined(WITH_JIT)
1825#if 0
1826 /*
1827 * For debugging. If jitResumeDPC is non-zero, then
1828 * we expect to return to a trace in progress. There
1829 * are valid reasons why we wouldn't (such as an exception
1830 * throw), but here we can keep track.
1831 */
1832 if (self->jitResumeDPC != NULL) {
1833 if (self->jitResumeDPC == pc) {
1834 if (self->jitResumeNPC != NULL) {
1835 LOGD("SS return to trace - pc:0x%x to 0x:%x",
1836 (int)pc, (int)self->jitResumeNPC);
1837 } else {
1838 LOGD("SS return to interp - pc:0x%x",(int)pc);
1839 }
1840 } else {
1841 LOGD("SS failed to return. Expected 0x%x, now at 0x%x",
1842 (int)self->jitResumeDPC, (int)pc);
1843 }
1844 }
1845#endif
1846 // If we've got a native return and no other reasons to
1847 // remain in singlestep/break mode, do a long jump
1848 if (self->jitResumeNPC != NULL &&
1849 self->interpBreak.ctl.breakFlags == 0) {
1850 assert(self->jitResumeDPC == pc);
1851 self->jitResumeDPC = NULL;
1852 dvmJitResumeTranslation(self, pc, fp);
1853 // Doesn't return
1854 dvmAbort();
1855 }
1856 self->jitResumeDPC = NULL;
buzbee7209bdd2011-03-31 15:38:34 -07001857 self->inJitCodeCache = NULL;
buzbee9a3147c2011-03-02 15:43:48 -08001858#endif
1859 } else {
1860 self->singleStepCount--;
1861#if defined(WITH_JIT)
1862 if ((self->singleStepCount > 0) && (self->jitResumeNPC != NULL)) {
1863 /*
1864 * Direct return to an existing translation following a
1865 * single step is valid only if we step once. If we're
1866 * here, an additional step was added so we need to invalidate
1867 * the return to translation.
1868 */
1869 self->jitResumeNPC = NULL;
buzbee7209bdd2011-03-31 15:38:34 -07001870 self->inJitCodeCache = NULL;
buzbee9a3147c2011-03-02 15:43:48 -08001871 }
1872#endif
1873 }
1874 }
buzbeea7d59bb2011-02-24 09:38:17 -08001875}
buzbee9f601a92011-02-11 17:48:20 -08001876
1877/*
buzbee9a3147c2011-03-02 15:43:48 -08001878 * Main interpreter loop entry point.
buzbee9f601a92011-02-11 17:48:20 -08001879 *
1880 * This begins executing code at the start of "method". On exit, "pResult"
1881 * holds the return value of the method (or, if "method" returns NULL, it
1882 * holds an undefined value).
1883 *
1884 * The interpreted stack frame, which holds the method arguments, has
1885 * already been set up.
1886 */
1887void dvmInterpret(Thread* self, const Method* method, JValue* pResult)
1888{
buzbee9f601a92011-02-11 17:48:20 -08001889 InterpSaveState interpSaveState;
buzbee9a3147c2011-03-02 15:43:48 -08001890 int savedBreakFlags;
1891 int savedSubModes;
1892
buzbee9f601a92011-02-11 17:48:20 -08001893#if defined(WITH_JIT)
1894 /* Target-specific save/restore */
1895 extern void dvmJitCalleeSave(double *saveArea);
1896 extern void dvmJitCalleeRestore(double *saveArea);
1897 double calleeSave[JIT_CALLEE_SAVE_DOUBLE_COUNT];
Ben Cheng7a2697d2010-06-07 13:44:23 -07001898 /*
1899 * If the previous VM left the code cache through single-stepping the
1900 * inJitCodeCache flag will be set when the VM is re-entered (for example,
1901 * in self-verification mode we single-step NEW_INSTANCE which may re-enter
1902 * the VM through findClassFromLoaderNoInit). Because of that, we cannot
1903 * assert that self->inJitCodeCache is NULL here.
1904 */
Ben Chengba4fc8b2009-06-01 13:00:29 -07001905#endif
1906
buzbee9f601a92011-02-11 17:48:20 -08001907 /*
1908 * Save interpreter state from previous activation, linking
1909 * new to last.
1910 */
1911 interpSaveState = self->interpSave;
1912 self->interpSave.prev = &interpSaveState;
buzbee9a3147c2011-03-02 15:43:48 -08001913 /*
1914 * Strip out and save any flags that should not be inherited by
1915 * nested interpreter activation.
1916 */
1917 savedBreakFlags = self->interpBreak.ctl.breakFlags & LOCAL_BREAKFLAGS;
1918 savedSubModes = self->interpBreak.ctl.subMode & LOCAL_SUBMODE;
1919 if (savedBreakFlags | savedSubModes) {
1920 dvmUpdateInterpBreak(self, savedBreakFlags, savedSubModes,
1921 false /*disable*/);
1922 }
buzbee9f601a92011-02-11 17:48:20 -08001923#if defined(WITH_JIT)
1924 dvmJitCalleeSave(calleeSave);
1925#endif
1926
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001927
1928#if defined(WITH_TRACKREF_CHECKS)
buzbeeef5db622011-02-22 14:01:46 -08001929 self->interpSave.debugTrackedRefStart =
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001930 dvmReferenceTableEntries(&self->internalLocalRefTable);
1931#endif
buzbee9f601a92011-02-11 17:48:20 -08001932 self->debugIsMethodEntry = true;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001933#if defined(WITH_JIT)
buzbee9f601a92011-02-11 17:48:20 -08001934 dvmJitCalleeSave(calleeSave);
Ben Chenga4973592010-03-31 11:59:18 -07001935 /* Initialize the state to kJitNot */
buzbee9f601a92011-02-11 17:48:20 -08001936 self->jitState = kJitNot;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001937#endif
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001938
1939 /*
1940 * Initialize working state.
1941 *
1942 * No need to initialize "retval".
1943 */
buzbee9f601a92011-02-11 17:48:20 -08001944 self->interpSave.method = method;
1945 self->interpSave.fp = (u4*) self->curFrame;
1946 self->interpSave.pc = method->insns;
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001947
1948 assert(!dvmIsNativeMethod(method));
1949
1950 /*
1951 * Make sure the class is ready to go. Shouldn't be possible to get
1952 * here otherwise.
1953 */
1954 if (method->clazz->status < CLASS_INITIALIZING ||
1955 method->clazz->status == CLASS_ERROR)
1956 {
1957 LOGE("ERROR: tried to execute code in unprepared class '%s' (%d)\n",
1958 method->clazz->descriptor, method->clazz->status);
1959 dvmDumpThread(self, false);
1960 dvmAbort();
1961 }
1962
buzbee9a3147c2011-03-02 15:43:48 -08001963 typedef void (*Interpreter)(Thread*);
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001964 Interpreter stdInterp;
1965 if (gDvm.executionMode == kExecutionModeInterpFast)
1966 stdInterp = dvmMterpStd;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001967#if defined(WITH_JIT)
1968 else if (gDvm.executionMode == kExecutionModeJit)
Ben Chengba4fc8b2009-06-01 13:00:29 -07001969 stdInterp = dvmMterpStd;
1970#endif
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001971 else
buzbee9a3147c2011-03-02 15:43:48 -08001972 stdInterp = dvmInterpretPortable;
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001973
buzbee9a3147c2011-03-02 15:43:48 -08001974 // Call the interpreter
1975 (*stdInterp)(self);
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001976
buzbee9f601a92011-02-11 17:48:20 -08001977 *pResult = self->retval;
1978
1979 /* Restore interpreter state from previous activation */
1980 self->interpSave = interpSaveState;
Bill Buzbee342806d2009-12-08 12:37:13 -08001981#if defined(WITH_JIT)
buzbee9f601a92011-02-11 17:48:20 -08001982 dvmJitCalleeRestore(calleeSave);
Bill Buzbee342806d2009-12-08 12:37:13 -08001983#endif
buzbee9a3147c2011-03-02 15:43:48 -08001984 if (savedBreakFlags | savedSubModes) {
1985 dvmUpdateInterpBreak(self, savedBreakFlags, savedSubModes,
1986 true /*enable*/);
1987 }
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001988}