blob: 9e94449755192d1ba0b35178282aa84e408a25d1 [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"
28
29
30/*
31 * ===========================================================================
32 * Debugger support
33 * ===========================================================================
34 */
35
Andy McFadden96516932009-10-28 17:39:02 -070036// fwd
37static BreakpointSet* dvmBreakpointSetAlloc(void);
38static void dvmBreakpointSetFree(BreakpointSet* pSet);
39
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -070040/*
Andy McFadden96516932009-10-28 17:39:02 -070041 * Initialize global breakpoint structures.
42 */
43bool dvmBreakpointStartup(void)
44{
Andy McFadden96516932009-10-28 17:39:02 -070045 gDvm.breakpointSet = dvmBreakpointSetAlloc();
46 return (gDvm.breakpointSet != NULL);
Andy McFadden96516932009-10-28 17:39:02 -070047}
48
49/*
50 * Free resources.
51 */
52void dvmBreakpointShutdown(void)
53{
Andy McFadden96516932009-10-28 17:39:02 -070054 dvmBreakpointSetFree(gDvm.breakpointSet);
Andy McFadden96516932009-10-28 17:39:02 -070055}
56
57
Andy McFadden96516932009-10-28 17:39:02 -070058/*
59 * This represents a breakpoint inserted in the instruction stream.
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -070060 *
Andy McFadden96516932009-10-28 17:39:02 -070061 * The debugger may ask us to create the same breakpoint multiple times.
62 * We only remove the breakpoint when the last instance is cleared.
63 */
64typedef struct {
Andy McFaddend22748a2010-04-22 17:08:11 -070065 Method* method; /* method we're associated with */
Andy McFadden96516932009-10-28 17:39:02 -070066 u2* addr; /* absolute memory address */
Dan Bornstein9a1f8162010-12-01 17:02:26 -080067 u1 originalOpcode; /* original 8-bit opcode value */
Andy McFadden96516932009-10-28 17:39:02 -070068 int setCount; /* #of times this breakpoint was set */
69} Breakpoint;
70
71/*
72 * Set of breakpoints.
73 */
74struct BreakpointSet {
75 /* grab lock before reading or writing anything else in here */
76 pthread_mutex_t lock;
77
78 /* vector of breakpoint structures */
79 int alloc;
80 int count;
81 Breakpoint* breakpoints;
82};
83
84/*
85 * Initialize a BreakpointSet. Initially empty.
86 */
87static BreakpointSet* dvmBreakpointSetAlloc(void)
88{
89 BreakpointSet* pSet = (BreakpointSet*) calloc(1, sizeof(*pSet));
90
91 dvmInitMutex(&pSet->lock);
92 /* leave the rest zeroed -- will alloc on first use */
93
94 return pSet;
95}
96
97/*
98 * Free storage associated with a BreakpointSet.
99 */
100static void dvmBreakpointSetFree(BreakpointSet* pSet)
101{
102 if (pSet == NULL)
103 return;
104
105 free(pSet->breakpoints);
106 free(pSet);
107}
108
109/*
110 * Lock the breakpoint set.
Andy McFaddend22748a2010-04-22 17:08:11 -0700111 *
112 * It's not currently necessary to switch to VMWAIT in the event of
113 * contention, because nothing in here can block. However, it's possible
114 * that the bytecode-updater code could become fancier in the future, so
115 * we do the trylock dance as a bit of future-proofing.
Andy McFadden96516932009-10-28 17:39:02 -0700116 */
117static void dvmBreakpointSetLock(BreakpointSet* pSet)
118{
Andy McFaddend22748a2010-04-22 17:08:11 -0700119 if (dvmTryLockMutex(&pSet->lock) != 0) {
120 Thread* self = dvmThreadSelf();
Carl Shapiro5617ad32010-07-02 10:50:57 -0700121 ThreadStatus oldStatus = dvmChangeStatus(self, THREAD_VMWAIT);
Andy McFaddend22748a2010-04-22 17:08:11 -0700122 dvmLockMutex(&pSet->lock);
123 dvmChangeStatus(self, oldStatus);
124 }
Andy McFadden96516932009-10-28 17:39:02 -0700125}
126
127/*
128 * Unlock the breakpoint set.
129 */
130static void dvmBreakpointSetUnlock(BreakpointSet* pSet)
131{
132 dvmUnlockMutex(&pSet->lock);
133}
134
135/*
136 * Return the #of breakpoints.
137 */
138static int dvmBreakpointSetCount(const BreakpointSet* pSet)
139{
140 return pSet->count;
141}
142
143/*
144 * See if we already have an entry for this address.
145 *
146 * The BreakpointSet's lock must be acquired before calling here.
147 *
148 * Returns the index of the breakpoint entry, or -1 if not found.
149 */
150static int dvmBreakpointSetFind(const BreakpointSet* pSet, const u2* addr)
151{
152 int i;
153
154 for (i = 0; i < pSet->count; i++) {
155 Breakpoint* pBreak = &pSet->breakpoints[i];
156 if (pBreak->addr == addr)
157 return i;
158 }
159
160 return -1;
161}
162
163/*
164 * Retrieve the opcode that was originally at the specified location.
165 *
166 * The BreakpointSet's lock must be acquired before calling here.
167 *
168 * Returns "true" with the opcode in *pOrig on success.
169 */
Dan Bornstein9a1f8162010-12-01 17:02:26 -0800170static bool dvmBreakpointSetOriginalOpcode(const BreakpointSet* pSet,
Andy McFadden96516932009-10-28 17:39:02 -0700171 const u2* addr, u1* pOrig)
172{
173 int idx = dvmBreakpointSetFind(pSet, addr);
174 if (idx < 0)
175 return false;
176
Dan Bornstein9a1f8162010-12-01 17:02:26 -0800177 *pOrig = pSet->breakpoints[idx].originalOpcode;
Andy McFadden96516932009-10-28 17:39:02 -0700178 return true;
179}
180
181/*
Andy McFaddenda9dc842010-05-03 16:11:20 -0700182 * Check the opcode. If it's a "magic" NOP, indicating the start of
183 * switch or array data in the instruction stream, we don't want to set
184 * a breakpoint.
185 *
186 * This can happen because the line number information dx generates
187 * associates the switch data with the switch statement's line number,
188 * and some debuggers put breakpoints at every address associated with
189 * a given line. The result is that the breakpoint stomps on the NOP
190 * instruction that doubles as a data table magic number, and an explicit
191 * check in the interpreter results in an exception being thrown.
192 *
193 * We don't want to simply refuse to add the breakpoint to the table,
194 * because that confuses the housekeeping. We don't want to reject the
195 * debugger's event request, and we want to be sure that there's exactly
196 * one un-set operation for every set op.
197 */
198static bool instructionIsMagicNop(const u2* addr)
199{
200 u2 curVal = *addr;
201 return ((curVal & 0xff) == OP_NOP && (curVal >> 8) != 0);
202}
203
204/*
Andy McFadden96516932009-10-28 17:39:02 -0700205 * Add a breakpoint at a specific address. If the address is already
206 * present in the table, this just increments the count.
207 *
208 * For a new entry, this will extract and preserve the current opcode from
209 * the instruction stream, and replace it with a breakpoint opcode.
210 *
211 * The BreakpointSet's lock must be acquired before calling here.
212 *
213 * Returns "true" on success.
214 */
215static bool dvmBreakpointSetAdd(BreakpointSet* pSet, Method* method,
216 unsigned int instrOffset)
217{
218 const int kBreakpointGrowth = 10;
219 const u2* addr = method->insns + instrOffset;
220 int idx = dvmBreakpointSetFind(pSet, addr);
221 Breakpoint* pBreak;
222
223 if (idx < 0) {
224 if (pSet->count == pSet->alloc) {
225 int newSize = pSet->alloc + kBreakpointGrowth;
226 Breakpoint* newVec;
227
228 LOGV("+++ increasing breakpoint set size to %d\n", newSize);
229
230 /* pSet->breakpoints will be NULL on first entry */
Carl Shapirofc75f3e2010-12-07 11:43:38 -0800231 newVec = (Breakpoint*)realloc(pSet->breakpoints, newSize * sizeof(Breakpoint));
Andy McFadden96516932009-10-28 17:39:02 -0700232 if (newVec == NULL)
233 return false;
234
235 pSet->breakpoints = newVec;
236 pSet->alloc = newSize;
237 }
238
239 pBreak = &pSet->breakpoints[pSet->count++];
Andy McFaddend22748a2010-04-22 17:08:11 -0700240 pBreak->method = method;
Andy McFadden96516932009-10-28 17:39:02 -0700241 pBreak->addr = (u2*)addr;
Dan Bornstein9a1f8162010-12-01 17:02:26 -0800242 pBreak->originalOpcode = *(u1*)addr;
Andy McFadden96516932009-10-28 17:39:02 -0700243 pBreak->setCount = 1;
244
245 /*
246 * Change the opcode. We must ensure that the BreakpointSet
247 * updates happen before we change the opcode.
Andy McFaddend22748a2010-04-22 17:08:11 -0700248 *
249 * If the method has not been verified, we do NOT insert the
250 * breakpoint yet, since that will screw up the verifier. The
251 * debugger is allowed to insert breakpoints in unverified code,
252 * but since we don't execute unverified code we don't need to
253 * alter the bytecode yet.
254 *
Andy McFaddenc7a12b22010-04-30 10:08:55 -0700255 * The class init code will "flush" all pending opcode writes
256 * before verification completes.
Andy McFadden96516932009-10-28 17:39:02 -0700257 */
Andy McFadden96516932009-10-28 17:39:02 -0700258 assert(*(u1*)addr != OP_BREAKPOINT);
Andy McFaddend22748a2010-04-22 17:08:11 -0700259 if (dvmIsClassVerified(method->clazz)) {
260 LOGV("Class %s verified, adding breakpoint at %p\n",
261 method->clazz->descriptor, addr);
Andy McFaddenda9dc842010-05-03 16:11:20 -0700262 if (instructionIsMagicNop(addr)) {
263 LOGV("Refusing to set breakpoint on %04x at %s.%s + 0x%x\n",
264 *addr, method->clazz->descriptor, method->name,
265 instrOffset);
266 } else {
Andy McFadden6e10b9a2010-06-14 15:24:39 -0700267 ANDROID_MEMBAR_FULL();
Andy McFaddenda9dc842010-05-03 16:11:20 -0700268 dvmDexChangeDex1(method->clazz->pDvmDex, (u1*)addr,
269 OP_BREAKPOINT);
270 }
Andy McFaddend22748a2010-04-22 17:08:11 -0700271 } else {
272 LOGV("Class %s NOT verified, deferring breakpoint at %p\n",
273 method->clazz->descriptor, addr);
274 }
Andy McFadden96516932009-10-28 17:39:02 -0700275 } else {
Andy McFaddenc7a12b22010-04-30 10:08:55 -0700276 /*
277 * Breakpoint already exists, just increase the count.
278 */
Andy McFadden96516932009-10-28 17:39:02 -0700279 pBreak = &pSet->breakpoints[idx];
280 pBreak->setCount++;
Andy McFadden96516932009-10-28 17:39:02 -0700281 }
282
283 return true;
284}
285
286/*
287 * Remove one instance of the specified breakpoint. When the count
288 * reaches zero, the entry is removed from the table, and the original
289 * opcode is restored.
290 *
291 * The BreakpointSet's lock must be acquired before calling here.
292 */
293static void dvmBreakpointSetRemove(BreakpointSet* pSet, Method* method,
294 unsigned int instrOffset)
295{
296 const u2* addr = method->insns + instrOffset;
297 int idx = dvmBreakpointSetFind(pSet, addr);
298
299 if (idx < 0) {
300 /* breakpoint not found in set -- unexpected */
301 if (*(u1*)addr == OP_BREAKPOINT) {
Andy McFaddenda9dc842010-05-03 16:11:20 -0700302 LOGE("Unable to restore breakpoint opcode (%s.%s +0x%x)\n",
Andy McFadden96516932009-10-28 17:39:02 -0700303 method->clazz->descriptor, method->name, instrOffset);
304 dvmAbort();
305 } else {
Andy McFaddenda9dc842010-05-03 16:11:20 -0700306 LOGW("Breakpoint was already restored? (%s.%s +0x%x)\n",
Andy McFadden96516932009-10-28 17:39:02 -0700307 method->clazz->descriptor, method->name, instrOffset);
308 }
309 } else {
310 Breakpoint* pBreak = &pSet->breakpoints[idx];
311 if (pBreak->setCount == 1) {
312 /*
313 * Must restore opcode before removing set entry.
Andy McFaddend22748a2010-04-22 17:08:11 -0700314 *
315 * If the breakpoint was never flushed, we could be ovewriting
316 * a value with the same value. Not a problem, though we
317 * could end up causing a copy-on-write here when we didn't
318 * need to. (Not worth worrying about.)
Andy McFadden96516932009-10-28 17:39:02 -0700319 */
320 dvmDexChangeDex1(method->clazz->pDvmDex, (u1*)addr,
Dan Bornstein9a1f8162010-12-01 17:02:26 -0800321 pBreak->originalOpcode);
Andy McFadden6e10b9a2010-06-14 15:24:39 -0700322 ANDROID_MEMBAR_FULL();
Andy McFadden96516932009-10-28 17:39:02 -0700323
324 if (idx != pSet->count-1) {
325 /* shift down */
326 memmove(&pSet->breakpoints[idx], &pSet->breakpoints[idx+1],
327 (pSet->count-1 - idx) * sizeof(pSet->breakpoints[0]));
328 }
329 pSet->count--;
330 pSet->breakpoints[pSet->count].addr = (u2*) 0xdecadead; // debug
331 } else {
332 pBreak->setCount--;
333 assert(pBreak->setCount > 0);
334 }
335 }
336}
337
338/*
Andy McFaddend22748a2010-04-22 17:08:11 -0700339 * Flush any breakpoints associated with methods in "clazz". We want to
340 * change the opcode, which might not have happened when the breakpoint
341 * was initially set because the class was in the process of being
342 * verified.
Andy McFadden96516932009-10-28 17:39:02 -0700343 *
344 * The BreakpointSet's lock must be acquired before calling here.
345 */
Andy McFaddend22748a2010-04-22 17:08:11 -0700346static void dvmBreakpointSetFlush(BreakpointSet* pSet, ClassObject* clazz)
Andy McFadden96516932009-10-28 17:39:02 -0700347{
Andy McFadden96516932009-10-28 17:39:02 -0700348 int i;
349 for (i = 0; i < pSet->count; i++) {
350 Breakpoint* pBreak = &pSet->breakpoints[i];
Andy McFaddend22748a2010-04-22 17:08:11 -0700351 if (pBreak->method->clazz == clazz) {
352 /*
353 * The breakpoint is associated with a method in this class.
354 * It might already be there or it might not; either way,
355 * flush it out.
356 */
357 LOGV("Flushing breakpoint at %p for %s\n",
358 pBreak->addr, clazz->descriptor);
Andy McFaddenda9dc842010-05-03 16:11:20 -0700359 if (instructionIsMagicNop(pBreak->addr)) {
Andy McFaddenda9dc842010-05-03 16:11:20 -0700360 LOGV("Refusing to flush breakpoint on %04x at %s.%s + 0x%x\n",
Carl Shapiroe3c01da2010-05-20 22:54:18 -0700361 *pBreak->addr, pBreak->method->clazz->descriptor,
362 pBreak->method->name, pBreak->addr - pBreak->method->insns);
Andy McFaddenda9dc842010-05-03 16:11:20 -0700363 } else {
364 dvmDexChangeDex1(clazz->pDvmDex, (u1*)pBreak->addr,
365 OP_BREAKPOINT);
366 }
Andy McFadden96516932009-10-28 17:39:02 -0700367 }
368 }
369}
Andy McFadden96516932009-10-28 17:39:02 -0700370
371
372/*
373 * Do any debugger-attach-time initialization.
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700374 */
375void dvmInitBreakpoints(void)
376{
Andy McFadden96516932009-10-28 17:39:02 -0700377 /* quick sanity check */
378 BreakpointSet* pSet = gDvm.breakpointSet;
379 dvmBreakpointSetLock(pSet);
380 if (dvmBreakpointSetCount(pSet) != 0) {
381 LOGW("WARNING: %d leftover breakpoints\n", dvmBreakpointSetCount(pSet));
382 /* generally not good, but we can keep going */
383 }
384 dvmBreakpointSetUnlock(pSet);
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700385}
386
387/*
388 * Add an address to the list, putting it in the first non-empty slot.
389 *
390 * Sometimes the debugger likes to add two entries for one breakpoint.
391 * We add two entries here, so that we get the right behavior when it's
392 * removed twice.
393 *
394 * This will only be run from the JDWP thread, and it will happen while
395 * we are updating the event list, which is synchronized. We're guaranteed
396 * to be the only one adding entries, and the lock ensures that nobody
397 * will be trying to remove them while we're in here.
398 *
399 * "addr" is the absolute address of the breakpoint bytecode.
400 */
Andy McFadden96516932009-10-28 17:39:02 -0700401void dvmAddBreakAddr(Method* method, unsigned int instrOffset)
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700402{
Andy McFadden96516932009-10-28 17:39:02 -0700403 BreakpointSet* pSet = gDvm.breakpointSet;
404 dvmBreakpointSetLock(pSet);
405 dvmBreakpointSetAdd(pSet, method, instrOffset);
406 dvmBreakpointSetUnlock(pSet);
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700407}
408
409/*
410 * Remove an address from the list by setting the entry to NULL.
411 *
412 * This can be called from the JDWP thread (because the debugger has
413 * cancelled the breakpoint) or from an event thread (because it's a
414 * single-shot breakpoint, e.g. "run to line"). We only get here as
415 * the result of removing an entry from the event list, which is
416 * synchronized, so it should not be possible for two threads to be
417 * updating breakpoints at the same time.
418 */
Andy McFadden96516932009-10-28 17:39:02 -0700419void dvmClearBreakAddr(Method* method, unsigned int instrOffset)
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700420{
Andy McFadden96516932009-10-28 17:39:02 -0700421 BreakpointSet* pSet = gDvm.breakpointSet;
422 dvmBreakpointSetLock(pSet);
423 dvmBreakpointSetRemove(pSet, method, instrOffset);
424 dvmBreakpointSetUnlock(pSet);
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700425}
426
Andy McFadden96516932009-10-28 17:39:02 -0700427/*
428 * Get the original opcode from under a breakpoint.
Andy McFaddenfc3d3162010-08-05 14:34:26 -0700429 *
430 * On SMP hardware it's possible one core might try to execute a breakpoint
431 * after another core has cleared it. We need to handle the case where
432 * there's no entry in the breakpoint set. (The memory barriers in the
433 * locks and in the breakpoint update code should ensure that, once we've
434 * observed the absence of a breakpoint entry, we will also now observe
435 * the restoration of the original opcode. The fact that we're holding
436 * the lock prevents other threads from confusing things further.)
Andy McFadden96516932009-10-28 17:39:02 -0700437 */
Dan Bornstein9a1f8162010-12-01 17:02:26 -0800438u1 dvmGetOriginalOpcode(const u2* addr)
Andy McFadden96516932009-10-28 17:39:02 -0700439{
440 BreakpointSet* pSet = gDvm.breakpointSet;
441 u1 orig = 0;
442
443 dvmBreakpointSetLock(pSet);
Dan Bornstein9a1f8162010-12-01 17:02:26 -0800444 if (!dvmBreakpointSetOriginalOpcode(pSet, addr, &orig)) {
Andy McFadden96516932009-10-28 17:39:02 -0700445 orig = *(u1*)addr;
446 if (orig == OP_BREAKPOINT) {
447 LOGE("GLITCH: can't find breakpoint, opcode is still set\n");
448 dvmAbort();
449 }
450 }
451 dvmBreakpointSetUnlock(pSet);
452
453 return orig;
454}
455
456/*
Andy McFaddend22748a2010-04-22 17:08:11 -0700457 * Flush any breakpoints associated with methods in "clazz".
Andy McFadden96516932009-10-28 17:39:02 -0700458 *
Andy McFaddend22748a2010-04-22 17:08:11 -0700459 * We don't want to modify the bytecode of a method before the verifier
460 * gets a chance to look at it, so we postpone opcode replacement until
461 * after verification completes.
Andy McFadden96516932009-10-28 17:39:02 -0700462 */
Andy McFaddend22748a2010-04-22 17:08:11 -0700463void dvmFlushBreakpoints(ClassObject* clazz)
Andy McFadden96516932009-10-28 17:39:02 -0700464{
465 BreakpointSet* pSet = gDvm.breakpointSet;
466
Andy McFaddend22748a2010-04-22 17:08:11 -0700467 if (pSet == NULL)
468 return;
469
470 assert(dvmIsClassVerified(clazz));
Andy McFadden96516932009-10-28 17:39:02 -0700471 dvmBreakpointSetLock(pSet);
Andy McFaddend22748a2010-04-22 17:08:11 -0700472 dvmBreakpointSetFlush(pSet, clazz);
Andy McFadden96516932009-10-28 17:39:02 -0700473 dvmBreakpointSetUnlock(pSet);
474}
Andy McFadden96516932009-10-28 17:39:02 -0700475
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700476/*
477 * Add a single step event. Currently this is a global item.
478 *
479 * We set up some initial values based on the thread's current state. This
480 * won't work well if the thread is running, so it's up to the caller to
481 * verify that it's suspended.
482 *
483 * This is only called from the JDWP thread.
484 */
485bool dvmAddSingleStep(Thread* thread, int size, int depth)
486{
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700487 StepControl* pCtrl = &gDvm.stepControl;
488
489 if (pCtrl->active && thread != pCtrl->thread) {
490 LOGW("WARNING: single-step active for %p; adding %p\n",
491 pCtrl->thread, thread);
492
493 /*
494 * Keep going, overwriting previous. This can happen if you
495 * suspend a thread in Object.wait, hit the single-step key, then
496 * switch to another thread and do the same thing again.
497 * The first thread's step is still pending.
498 *
499 * TODO: consider making single-step per-thread. Adds to the
500 * overhead, but could be useful in rare situations.
501 */
502 }
503
504 pCtrl->size = size;
505 pCtrl->depth = depth;
506 pCtrl->thread = thread;
507
508 /*
509 * We may be stepping into or over method calls, or running until we
510 * return from the current method. To make this work we need to track
511 * the current line, current method, and current stack depth. We need
512 * to be checking these after most instructions, notably those that
513 * call methods, return from methods, or are on a different line from the
514 * previous instruction.
515 *
516 * We have to start with a snapshot of the current state. If we're in
517 * an interpreted method, everything we need is in the current frame. If
518 * we're in a native method, possibly with some extra JNI frames pushed
519 * on by PushLocalFrame, we want to use the topmost native method.
520 */
521 const StackSaveArea* saveArea;
522 void* fp;
523 void* prevFp = NULL;
Ben Cheng38329f52009-07-07 14:19:20 -0700524
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700525 for (fp = thread->curFrame; fp != NULL; fp = saveArea->prevFrame) {
526 const Method* method;
527
528 saveArea = SAVEAREA_FROM_FP(fp);
529 method = saveArea->method;
530
Carl Shapirofc75f3e2010-12-07 11:43:38 -0800531 if (!dvmIsBreakFrame((u4*)fp) && !dvmIsNativeMethod(method))
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700532 break;
533 prevFp = fp;
534 }
535 if (fp == NULL) {
536 LOGW("Unexpected: step req in native-only threadid=%d\n",
537 thread->threadId);
538 return false;
539 }
540 if (prevFp != NULL) {
541 /*
542 * First interpreted frame wasn't the one at the bottom. Break
543 * frames are only inserted when calling from native->interp, so we
544 * don't need to worry about one being here.
545 */
546 LOGV("##### init step while in native method\n");
547 fp = prevFp;
Carl Shapirofc75f3e2010-12-07 11:43:38 -0800548 assert(!dvmIsBreakFrame((u4*)fp));
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700549 assert(dvmIsNativeMethod(SAVEAREA_FROM_FP(fp)->method));
550 saveArea = SAVEAREA_FROM_FP(fp);
551 }
552
553 /*
554 * Pull the goodies out. "xtra.currentPc" should be accurate since
555 * we update it on every instruction while the debugger is connected.
556 */
557 pCtrl->method = saveArea->method;
558 // Clear out any old address set
559 if (pCtrl->pAddressSet != NULL) {
560 // (discard const)
561 free((void *)pCtrl->pAddressSet);
562 pCtrl->pAddressSet = NULL;
563 }
564 if (dvmIsNativeMethod(pCtrl->method)) {
565 pCtrl->line = -1;
566 } else {
567 pCtrl->line = dvmLineNumFromPC(saveArea->method,
568 saveArea->xtra.currentPc - saveArea->method->insns);
Ben Cheng38329f52009-07-07 14:19:20 -0700569 pCtrl->pAddressSet
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700570 = dvmAddressSetForLine(saveArea->method, pCtrl->line);
571 }
572 pCtrl->frameDepth = dvmComputeVagueFrameDepth(thread, thread->curFrame);
573 pCtrl->active = true;
574
575 LOGV("##### step init: thread=%p meth=%p '%s' line=%d frameDepth=%d depth=%s size=%s\n",
576 pCtrl->thread, pCtrl->method, pCtrl->method->name,
577 pCtrl->line, pCtrl->frameDepth,
578 dvmJdwpStepDepthStr(pCtrl->depth),
579 dvmJdwpStepSizeStr(pCtrl->size));
580
581 return true;
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700582}
583
584/*
585 * Disable a single step event.
586 */
587void dvmClearSingleStep(Thread* thread)
588{
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700589 UNUSED_PARAMETER(thread);
590
591 gDvm.stepControl.active = false;
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700592}
593
594
595/*
596 * Recover the "this" pointer from the current interpreted method. "this"
597 * is always in "in0" for non-static methods.
598 *
599 * The "ins" start at (#of registers - #of ins). Note in0 != v0.
600 *
601 * This works because "dx" guarantees that it will work. It's probably
602 * fairly common to have a virtual method that doesn't use its "this"
603 * pointer, in which case we're potentially wasting a register. However,
604 * the debugger doesn't treat "this" as just another argument. For
605 * example, events (such as breakpoints) can be enabled for specific
606 * values of "this". There is also a separate StackFrame.ThisObject call
607 * in JDWP that is expected to work for any non-native non-static method.
608 *
609 * Because we need it when setting up debugger event filters, we want to
610 * be able to do this quickly.
611 */
612Object* dvmGetThisPtr(const Method* method, const u4* fp)
613{
614 if (dvmIsStaticMethod(method))
615 return NULL;
616 return (Object*)fp[method->registersSize - method->insSize];
617}
618
619
620#if defined(WITH_TRACKREF_CHECKS)
621/*
622 * Verify that all internally-tracked references have been released. If
623 * they haven't, print them and abort the VM.
624 *
625 * "debugTrackedRefStart" indicates how many refs were on the list when
626 * we were first invoked.
627 */
628void dvmInterpCheckTrackedRefs(Thread* self, const Method* method,
629 int debugTrackedRefStart)
630{
631 if (dvmReferenceTableEntries(&self->internalLocalRefTable)
632 != (size_t) debugTrackedRefStart)
633 {
634 char* desc;
635 Object** top;
636 int count;
637
638 count = dvmReferenceTableEntries(&self->internalLocalRefTable);
639
640 LOGE("TRACK: unreleased internal reference (prev=%d total=%d)\n",
641 debugTrackedRefStart, count);
642 desc = dexProtoCopyMethodDescriptor(&method->prototype);
643 LOGE(" current method is %s.%s %s\n", method->clazz->descriptor,
644 method->name, desc);
645 free(desc);
646 top = self->internalLocalRefTable.table + debugTrackedRefStart;
647 while (top < self->internalLocalRefTable.nextEntry) {
648 LOGE(" %p (%s)\n",
649 *top,
650 ((*top)->clazz != NULL) ? (*top)->clazz->descriptor : "");
651 top++;
652 }
653 dvmDumpThread(self, false);
654
655 dvmAbort();
656 }
657 //LOGI("TRACK OK\n");
658}
659#endif
660
661
662#ifdef LOG_INSTR
663/*
664 * Dump the v-registers. Sent to the ILOG log tag.
665 */
666void dvmDumpRegs(const Method* method, const u4* framePtr, bool inOnly)
667{
668 int i, localCount;
669
670 localCount = method->registersSize - method->insSize;
671
672 LOG(LOG_VERBOSE, LOG_TAG"i", "Registers (fp=%p):\n", framePtr);
673 for (i = method->registersSize-1; i >= 0; i--) {
674 if (i >= localCount) {
675 LOG(LOG_VERBOSE, LOG_TAG"i", " v%-2d in%-2d : 0x%08x\n",
676 i, i-localCount, framePtr[i]);
677 } else {
678 if (inOnly) {
679 LOG(LOG_VERBOSE, LOG_TAG"i", " [...]\n");
680 break;
681 }
682 const char* name = "";
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700683#if 0 // "locals" structure has changed -- need to rewrite this
Elliott Hughes8afa9df2010-07-07 14:47:25 -0700684 int j;
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700685 DexFile* pDexFile = method->clazz->pDexFile;
686 const DexCode* pDexCode = dvmGetMethodCode(method);
687 int localsSize = dexGetLocalsSize(pDexFile, pDexCode);
688 const DexLocal* locals = dvmDexGetLocals(pDexFile, pDexCode);
689 for (j = 0; j < localsSize, j++) {
690 if (locals[j].registerNum == (u4) i) {
691 name = dvmDexStringStr(locals[j].pName);
692 break;
693 }
694 }
695#endif
696 LOG(LOG_VERBOSE, LOG_TAG"i", " v%-2d : 0x%08x %s\n",
697 i, framePtr[i], name);
698 }
699 }
700}
701#endif
702
703
704/*
705 * ===========================================================================
706 * Entry point and general support functions
707 * ===========================================================================
708 */
709
Ben Cheng38329f52009-07-07 14:19:20 -0700710/*
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700711 * Construct an s4 from two consecutive half-words of switch data.
712 * This needs to check endianness because the DEX optimizer only swaps
713 * half-words in instruction stream.
714 *
715 * "switchData" must be 32-bit aligned.
716 */
717#if __BYTE_ORDER == __LITTLE_ENDIAN
718static inline s4 s4FromSwitchData(const void* switchData) {
719 return *(s4*) switchData;
720}
721#else
722static inline s4 s4FromSwitchData(const void* switchData) {
723 u2* data = switchData;
724 return data[0] | (((s4) data[1]) << 16);
Jay Freeman (saurik)ffa5c292008-11-16 13:51:51 +0000725}
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700726#endif
727
728/*
729 * Find the matching case. Returns the offset to the handler instructions.
730 *
731 * Returns 3 if we don't find a match (it's the size of the packed-switch
732 * instruction).
733 */
734s4 dvmInterpHandlePackedSwitch(const u2* switchData, s4 testVal)
735{
736 const int kInstrLen = 3;
737 u2 size;
738 s4 firstKey;
739 const s4* entries;
740
741 /*
742 * Packed switch data format:
743 * ushort ident = 0x0100 magic value
744 * ushort size number of entries in the table
745 * int first_key first (and lowest) switch case value
746 * int targets[size] branch targets, relative to switch opcode
747 *
748 * Total size is (4+size*2) 16-bit code units.
749 */
750 if (*switchData++ != kPackedSwitchSignature) {
751 /* should have been caught by verifier */
Dan Bornsteind27f3cf2011-02-23 13:07:07 -0800752 dvmThrowInternalError("bad packed switch magic");
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700753 return kInstrLen;
754 }
755
756 size = *switchData++;
757 assert(size > 0);
758
759 firstKey = *switchData++;
760 firstKey |= (*switchData++) << 16;
761
762 if (testVal < firstKey || testVal >= firstKey + size) {
763 LOGVV("Value %d not found in switch (%d-%d)\n",
764 testVal, firstKey, firstKey+size-1);
765 return kInstrLen;
766 }
767
768 /* The entries are guaranteed to be aligned on a 32-bit boundary;
769 * we can treat them as a native int array.
770 */
771 entries = (const s4*) switchData;
772 assert(((u4)entries & 0x3) == 0);
773
774 assert(testVal - firstKey >= 0 && testVal - firstKey < size);
775 LOGVV("Value %d found in slot %d (goto 0x%02x)\n",
776 testVal, testVal - firstKey,
777 s4FromSwitchData(&entries[testVal - firstKey]));
778 return s4FromSwitchData(&entries[testVal - firstKey]);
779}
780
781/*
782 * Find the matching case. Returns the offset to the handler instructions.
783 *
784 * Returns 3 if we don't find a match (it's the size of the sparse-switch
785 * instruction).
786 */
787s4 dvmInterpHandleSparseSwitch(const u2* switchData, s4 testVal)
788{
789 const int kInstrLen = 3;
Carl Shapiroe3c01da2010-05-20 22:54:18 -0700790 u2 size;
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700791 const s4* keys;
792 const s4* entries;
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700793
794 /*
795 * Sparse switch data format:
796 * ushort ident = 0x0200 magic value
797 * ushort size number of entries in the table; > 0
798 * int keys[size] keys, sorted low-to-high; 32-bit aligned
799 * int targets[size] branch targets, relative to switch opcode
800 *
801 * Total size is (2+size*4) 16-bit code units.
802 */
803
804 if (*switchData++ != kSparseSwitchSignature) {
805 /* should have been caught by verifier */
Dan Bornsteind27f3cf2011-02-23 13:07:07 -0800806 dvmThrowInternalError("bad sparse switch magic");
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700807 return kInstrLen;
808 }
809
810 size = *switchData++;
811 assert(size > 0);
Ben Cheng38329f52009-07-07 14:19:20 -0700812
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700813 /* The keys are guaranteed to be aligned on a 32-bit boundary;
814 * we can treat them as a native int array.
815 */
816 keys = (const s4*) switchData;
817 assert(((u4)keys & 0x3) == 0);
818
819 /* The entries are guaranteed to be aligned on a 32-bit boundary;
820 * we can treat them as a native int array.
821 */
822 entries = keys + size;
823 assert(((u4)entries & 0x3) == 0);
824
825 /*
Andy McFadden62f19152009-10-21 16:59:31 -0700826 * Binary-search through the array of keys, which are guaranteed to
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700827 * be sorted low-to-high.
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700828 */
Andy McFadden62f19152009-10-21 16:59:31 -0700829 int lo = 0;
830 int hi = size - 1;
831 while (lo <= hi) {
832 int mid = (lo + hi) >> 1;
833
834 s4 foundVal = s4FromSwitchData(&keys[mid]);
835 if (testVal < foundVal) {
836 hi = mid - 1;
837 } else if (testVal > foundVal) {
838 lo = mid + 1;
839 } else {
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700840 LOGVV("Value %d found in entry %d (goto 0x%02x)\n",
Andy McFadden62f19152009-10-21 16:59:31 -0700841 testVal, mid, s4FromSwitchData(&entries[mid]));
842 return s4FromSwitchData(&entries[mid]);
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700843 }
844 }
845
846 LOGVV("Value %d not found in switch\n", testVal);
847 return kInstrLen;
848}
849
850/*
Andy McFadden6f214502009-06-30 16:14:30 -0700851 * Copy data for a fill-array-data instruction. On a little-endian machine
852 * we can just do a memcpy(), on a big-endian system we have work to do.
853 *
854 * The trick here is that dexopt has byte-swapped each code unit, which is
855 * exactly what we want for short/char data. For byte data we need to undo
856 * the swap, and for 4- or 8-byte values we need to swap pieces within
857 * each word.
858 */
859static void copySwappedArrayData(void* dest, const u2* src, u4 size, u2 width)
860{
861#if __BYTE_ORDER == __LITTLE_ENDIAN
862 memcpy(dest, src, size*width);
863#else
864 int i;
865
866 switch (width) {
867 case 1:
868 /* un-swap pairs of bytes as we go */
869 for (i = (size-1) & ~1; i >= 0; i -= 2) {
870 ((u1*)dest)[i] = ((u1*)src)[i+1];
871 ((u1*)dest)[i+1] = ((u1*)src)[i];
872 }
873 /*
874 * "src" is padded to end on a two-byte boundary, but we don't want to
875 * assume "dest" is, so we handle odd length specially.
876 */
877 if ((size & 1) != 0) {
878 ((u1*)dest)[size-1] = ((u1*)src)[size];
879 }
880 break;
881 case 2:
882 /* already swapped correctly */
883 memcpy(dest, src, size*width);
884 break;
885 case 4:
886 /* swap word halves */
887 for (i = 0; i < (int) size; i++) {
888 ((u4*)dest)[i] = (src[(i << 1) + 1] << 16) | src[i << 1];
889 }
890 break;
891 case 8:
892 /* swap word halves and words */
893 for (i = 0; i < (int) (size << 1); i += 2) {
894 ((int*)dest)[i] = (src[(i << 1) + 3] << 16) | src[(i << 1) + 2];
895 ((int*)dest)[i+1] = (src[(i << 1) + 1] << 16) | src[i << 1];
896 }
897 break;
898 default:
899 LOGE("Unexpected width %d in copySwappedArrayData\n", width);
900 dvmAbort();
901 break;
902 }
903#endif
904}
905
906/*
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700907 * Fill the array with predefined constant values.
908 *
909 * Returns true if job is completed, otherwise false to indicate that
910 * an exception has been thrown.
911 */
The Android Open Source Project89c1feb2008-12-17 18:03:55 -0800912bool dvmInterpHandleFillArrayData(ArrayObject* arrayObj, const u2* arrayData)
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700913{
914 u2 width;
915 u4 size;
916
The Android Open Source Project89c1feb2008-12-17 18:03:55 -0800917 if (arrayObj == NULL) {
Dan Bornsteind27f3cf2011-02-23 13:07:07 -0800918 dvmThrowNullPointerException(NULL);
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700919 return false;
920 }
Barry Hayes7dc96602010-02-24 09:19:07 -0800921 assert (!IS_CLASS_FLAG_SET(((Object *)arrayObj)->clazz,
922 CLASS_ISOBJECTARRAY));
The Android Open Source Project89c1feb2008-12-17 18:03:55 -0800923
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700924 /*
925 * Array data table format:
926 * ushort ident = 0x0300 magic value
927 * ushort width width of each element in the table
928 * uint size number of elements in the table
929 * ubyte data[size*width] table of data values (may contain a single-byte
930 * padding at the end)
931 *
932 * Total size is 4+(width * size + 1)/2 16-bit code units.
933 */
934 if (arrayData[0] != kArrayDataSignature) {
Dan Bornsteind27f3cf2011-02-23 13:07:07 -0800935 dvmThrowInternalError("bad array data magic");
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700936 return false;
937 }
938
939 width = arrayData[1];
940 size = arrayData[2] | (((u4)arrayData[3]) << 16);
941
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800942 if (size > arrayObj->length) {
Dan Bornstein74501e62011-02-24 10:32:47 -0800943 dvmThrowArrayIndexOutOfBoundsException(size, arrayObj->length);
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700944 return false;
945 }
Andy McFadden6f214502009-06-30 16:14:30 -0700946 copySwappedArrayData(arrayObj->contents, &arrayData[4], size, width);
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700947 return true;
948}
949
950/*
951 * Find the concrete method that corresponds to "methodIdx". The code in
952 * "method" is executing invoke-method with "thisClass" as its first argument.
953 *
954 * Returns NULL with an exception raised on failure.
955 */
956Method* dvmInterpFindInterfaceMethod(ClassObject* thisClass, u4 methodIdx,
957 const Method* method, DvmDex* methodClassDex)
958{
959 Method* absMethod;
960 Method* methodToCall;
961 int i, vtableIndex;
962
963 /*
964 * Resolve the method. This gives us the abstract method from the
965 * interface class declaration.
966 */
967 absMethod = dvmDexGetResolvedMethod(methodClassDex, methodIdx);
968 if (absMethod == NULL) {
969 absMethod = dvmResolveInterfaceMethod(method->clazz, methodIdx);
970 if (absMethod == NULL) {
971 LOGV("+ unknown method\n");
972 return NULL;
973 }
974 }
975
976 /* make sure absMethod->methodIndex means what we think it means */
977 assert(dvmIsAbstractMethod(absMethod));
978
979 /*
980 * Run through the "this" object's iftable. Find the entry for
981 * absMethod's class, then use absMethod->methodIndex to find
982 * the method's entry. The value there is the offset into our
983 * vtable of the actual method to execute.
984 *
985 * The verifier does not guarantee that objects stored into
986 * interface references actually implement the interface, so this
987 * check cannot be eliminated.
988 */
989 for (i = 0; i < thisClass->iftableCount; i++) {
990 if (thisClass->iftable[i].clazz == absMethod->clazz)
991 break;
992 }
993 if (i == thisClass->iftableCount) {
994 /* impossible in verified DEX, need to check for it in unverified */
Dan Bornstein70b00ab2011-02-23 14:11:27 -0800995 dvmThrowIncompatibleClassChangeError("interface not implemented");
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700996 return NULL;
997 }
998
999 assert(absMethod->methodIndex <
1000 thisClass->iftable[i].clazz->virtualMethodCount);
1001
1002 vtableIndex =
1003 thisClass->iftable[i].methodIndexArray[absMethod->methodIndex];
1004 assert(vtableIndex >= 0 && vtableIndex < thisClass->vtableCount);
1005 methodToCall = thisClass->vtable[vtableIndex];
1006
1007#if 0
1008 /* this can happen when there's a stale class file */
1009 if (dvmIsAbstractMethod(methodToCall)) {
Dan Bornsteind27f3cf2011-02-23 13:07:07 -08001010 dvmThrowAbstractMethodError("interface method not implemented");
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001011 return NULL;
1012 }
1013#else
1014 assert(!dvmIsAbstractMethod(methodToCall) ||
1015 methodToCall->nativeFunc != NULL);
1016#endif
1017
1018 LOGVV("+++ interface=%s.%s concrete=%s.%s\n",
1019 absMethod->clazz->descriptor, absMethod->name,
1020 methodToCall->clazz->descriptor, methodToCall->name);
1021 assert(methodToCall != NULL);
1022
1023 return methodToCall;
1024}
1025
1026
Andy McFaddenb51ea112009-05-08 16:50:17 -07001027
1028/*
1029 * Helpers for dvmThrowVerificationError().
1030 *
1031 * Each returns a newly-allocated string.
1032 */
1033#define kThrowShow_accessFromClass 1
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001034static char* classNameFromIndex(const Method* method, int ref,
1035 VerifyErrorRefType refType, int flags)
Andy McFaddenb51ea112009-05-08 16:50:17 -07001036{
1037 static const int kBufLen = 256;
1038 const DvmDex* pDvmDex = method->clazz->pDvmDex;
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001039
1040 if (refType == VERIFY_ERROR_REF_FIELD) {
1041 /* get class ID from field ID */
1042 const DexFieldId* pFieldId = dexGetFieldId(pDvmDex->pDexFile, ref);
1043 ref = pFieldId->classIdx;
1044 } else if (refType == VERIFY_ERROR_REF_METHOD) {
1045 /* get class ID from method ID */
1046 const DexMethodId* pMethodId = dexGetMethodId(pDvmDex->pDexFile, ref);
1047 ref = pMethodId->classIdx;
1048 }
1049
Andy McFaddenb51ea112009-05-08 16:50:17 -07001050 const char* className = dexStringByTypeIdx(pDvmDex->pDexFile, ref);
Elliott Hughes50169662010-11-22 13:14:23 -08001051 char* dotClassName = dvmHumanReadableDescriptor(className);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001052 if (flags == 0)
1053 return dotClassName;
1054
1055 char* result = (char*) malloc(kBufLen);
1056
1057 if ((flags & kThrowShow_accessFromClass) != 0) {
Elliott Hughes50169662010-11-22 13:14:23 -08001058 char* dotFromName =
1059 dvmHumanReadableDescriptor(method->clazz->descriptor);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001060 snprintf(result, kBufLen, "tried to access class %s from class %s",
1061 dotClassName, dotFromName);
1062 free(dotFromName);
1063 } else {
1064 assert(false); // should've been caught above
1065 result[0] = '\0';
1066 }
1067
1068 free(dotClassName);
1069 return result;
1070}
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001071static char* fieldNameFromIndex(const Method* method, int ref,
1072 VerifyErrorRefType refType, int flags)
Andy McFaddenb51ea112009-05-08 16:50:17 -07001073{
1074 static const int kBufLen = 256;
1075 const DvmDex* pDvmDex = method->clazz->pDvmDex;
1076 const DexFieldId* pFieldId;
1077 const char* className;
1078 const char* fieldName;
1079
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001080 if (refType != VERIFY_ERROR_REF_FIELD) {
1081 LOGW("Expected ref type %d, got %d\n", VERIFY_ERROR_REF_FIELD, refType);
1082 return NULL; /* no message */
1083 }
1084
Andy McFaddenb51ea112009-05-08 16:50:17 -07001085 pFieldId = dexGetFieldId(pDvmDex->pDexFile, ref);
1086 className = dexStringByTypeIdx(pDvmDex->pDexFile, pFieldId->classIdx);
1087 fieldName = dexStringById(pDvmDex->pDexFile, pFieldId->nameIdx);
1088
Elliott Hughes50169662010-11-22 13:14:23 -08001089 char* dotName = dvmHumanReadableDescriptor(className);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001090 char* result = (char*) malloc(kBufLen);
1091
1092 if ((flags & kThrowShow_accessFromClass) != 0) {
Elliott Hughes50169662010-11-22 13:14:23 -08001093 char* dotFromName =
1094 dvmHumanReadableDescriptor(method->clazz->descriptor);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001095 snprintf(result, kBufLen, "tried to access field %s.%s from class %s",
1096 dotName, fieldName, dotFromName);
1097 free(dotFromName);
1098 } else {
1099 snprintf(result, kBufLen, "%s.%s", dotName, fieldName);
1100 }
1101
1102 free(dotName);
1103 return result;
1104}
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001105static char* methodNameFromIndex(const Method* method, int ref,
1106 VerifyErrorRefType refType, int flags)
Andy McFaddenb51ea112009-05-08 16:50:17 -07001107{
1108 static const int kBufLen = 384;
1109 const DvmDex* pDvmDex = method->clazz->pDvmDex;
1110 const DexMethodId* pMethodId;
1111 const char* className;
1112 const char* methodName;
1113
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001114 if (refType != VERIFY_ERROR_REF_METHOD) {
1115 LOGW("Expected ref type %d, got %d\n", VERIFY_ERROR_REF_METHOD,refType);
1116 return NULL; /* no message */
1117 }
1118
Andy McFaddenb51ea112009-05-08 16:50:17 -07001119 pMethodId = dexGetMethodId(pDvmDex->pDexFile, ref);
1120 className = dexStringByTypeIdx(pDvmDex->pDexFile, pMethodId->classIdx);
1121 methodName = dexStringById(pDvmDex->pDexFile, pMethodId->nameIdx);
1122
Elliott Hughes50169662010-11-22 13:14:23 -08001123 char* dotName = dvmHumanReadableDescriptor(className);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001124 char* result = (char*) malloc(kBufLen);
1125
1126 if ((flags & kThrowShow_accessFromClass) != 0) {
Elliott Hughes50169662010-11-22 13:14:23 -08001127 char* dotFromName =
1128 dvmHumanReadableDescriptor(method->clazz->descriptor);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001129 char* desc = dexProtoCopyMethodDescriptor(&method->prototype);
1130 snprintf(result, kBufLen,
1131 "tried to access method %s.%s:%s from class %s",
1132 dotName, methodName, desc, dotFromName);
1133 free(dotFromName);
1134 free(desc);
1135 } else {
1136 snprintf(result, kBufLen, "%s.%s", dotName, methodName);
1137 }
1138
1139 free(dotName);
1140 return result;
1141}
1142
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001143/*
Andy McFadden3a1aedb2009-05-07 13:30:23 -07001144 * Throw an exception for a problem identified by the verifier.
1145 *
1146 * This is used by the invoke-verification-error instruction. It always
1147 * throws an exception.
1148 *
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001149 * "kind" indicates the kind of failure encountered by the verifier. It
1150 * has two parts, an error code and an indication of the reference type.
Andy McFadden3a1aedb2009-05-07 13:30:23 -07001151 */
Andy McFaddenb51ea112009-05-08 16:50:17 -07001152void dvmThrowVerificationError(const Method* method, int kind, int ref)
Andy McFadden3a1aedb2009-05-07 13:30:23 -07001153{
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001154 const int typeMask = 0xff << kVerifyErrorRefTypeShift;
1155 VerifyError errorKind = kind & ~typeMask;
1156 VerifyErrorRefType refType = kind >> kVerifyErrorRefTypeShift;
Andy McFaddenb51ea112009-05-08 16:50:17 -07001157 const char* exceptionName = "Ljava/lang/VerifyError;";
1158 char* msg = NULL;
1159
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001160 switch ((VerifyError) errorKind) {
Andy McFaddenb51ea112009-05-08 16:50:17 -07001161 case VERIFY_ERROR_NO_CLASS:
1162 exceptionName = "Ljava/lang/NoClassDefFoundError;";
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001163 msg = classNameFromIndex(method, ref, refType, 0);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001164 break;
1165 case VERIFY_ERROR_NO_FIELD:
1166 exceptionName = "Ljava/lang/NoSuchFieldError;";
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001167 msg = fieldNameFromIndex(method, ref, refType, 0);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001168 break;
1169 case VERIFY_ERROR_NO_METHOD:
1170 exceptionName = "Ljava/lang/NoSuchMethodError;";
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001171 msg = methodNameFromIndex(method, ref, refType, 0);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001172 break;
1173 case VERIFY_ERROR_ACCESS_CLASS:
1174 exceptionName = "Ljava/lang/IllegalAccessError;";
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001175 msg = classNameFromIndex(method, ref, refType,
1176 kThrowShow_accessFromClass);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001177 break;
1178 case VERIFY_ERROR_ACCESS_FIELD:
1179 exceptionName = "Ljava/lang/IllegalAccessError;";
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001180 msg = fieldNameFromIndex(method, ref, refType,
1181 kThrowShow_accessFromClass);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001182 break;
1183 case VERIFY_ERROR_ACCESS_METHOD:
1184 exceptionName = "Ljava/lang/IllegalAccessError;";
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001185 msg = methodNameFromIndex(method, ref, refType,
1186 kThrowShow_accessFromClass);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001187 break;
1188 case VERIFY_ERROR_CLASS_CHANGE:
1189 exceptionName = "Ljava/lang/IncompatibleClassChangeError;";
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001190 msg = classNameFromIndex(method, ref, refType, 0);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001191 break;
1192 case VERIFY_ERROR_INSTANTIATION:
1193 exceptionName = "Ljava/lang/InstantiationError;";
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001194 msg = classNameFromIndex(method, ref, refType, 0);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001195 break;
1196
1197 case VERIFY_ERROR_GENERIC:
1198 /* generic VerifyError; use default exception, no message */
1199 break;
1200 case VERIFY_ERROR_NONE:
1201 /* should never happen; use default exception */
1202 assert(false);
1203 msg = strdup("weird - no error specified");
1204 break;
1205
1206 /* no default clause -- want warning if enum updated */
1207 }
1208
1209 dvmThrowException(exceptionName, msg);
1210 free(msg);
Andy McFadden3a1aedb2009-05-07 13:30:23 -07001211}
1212
Andy McFadden3a1aedb2009-05-07 13:30:23 -07001213/*
buzbeecb3081f2011-01-14 13:37:31 -08001214 * Update interpBreak
1215 */
1216void dvmUpdateInterpBreak(int newMode, bool enable)
1217{
1218 ExecutionSubModes oldValue, newValue;
1219
1220 do {
1221 oldValue = gDvm.interpBreak;
1222 newValue = enable ? oldValue | newMode : oldValue & ~newMode;
1223 } while (android_atomic_release_cas(oldValue, newValue,
1224 &gDvm.interpBreak) != 0);
1225#if defined(WITH_JIT)
1226 dvmCompilerStateRefresh();
1227#endif
1228}
1229
1230/*
buzbee9f601a92011-02-11 17:48:20 -08001231 * One-time initialization at thread creation. Here we initialize
1232 * useful constants.
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001233 */
buzbee9f601a92011-02-11 17:48:20 -08001234void dvmInitInterpreterState(Thread* self)
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001235{
Ben Chengba4fc8b2009-06-01 13:00:29 -07001236#if defined(WITH_JIT)
1237 /* Interpreter entry points from compiled code */
1238 extern void dvmJitToInterpNormal();
1239 extern void dvmJitToInterpNoChain();
1240 extern void dvmJitToInterpPunt();
1241 extern void dvmJitToInterpSingleStep();
Ben Cheng40094c12010-02-24 20:58:44 -08001242 extern void dvmJitToInterpTraceSelect();
Jeff Hao97319a82009-08-12 16:57:15 -07001243#if defined(WITH_SELF_VERIFICATION)
Ben Cheng40094c12010-02-24 20:58:44 -08001244 extern void dvmJitToInterpBackwardBranch();
Jeff Hao97319a82009-08-12 16:57:15 -07001245#endif
Ben Cheng38329f52009-07-07 14:19:20 -07001246 /*
Ben Chengba4fc8b2009-06-01 13:00:29 -07001247 * Reserve a static entity here to quickly setup runtime contents as
1248 * gcc will issue block copy instructions.
1249 */
1250 static struct JitToInterpEntries jitToInterpEntries = {
1251 dvmJitToInterpNormal,
1252 dvmJitToInterpNoChain,
1253 dvmJitToInterpPunt,
1254 dvmJitToInterpSingleStep,
Ben Cheng40094c12010-02-24 20:58:44 -08001255 dvmJitToInterpTraceSelect,
Jeff Hao97319a82009-08-12 16:57:15 -07001256#if defined(WITH_SELF_VERIFICATION)
Ben Cheng40094c12010-02-24 20:58:44 -08001257 dvmJitToInterpBackwardBranch,
buzbee9f601a92011-02-11 17:48:20 -08001258#else
1259 NULL,
Jeff Hao97319a82009-08-12 16:57:15 -07001260#endif
Ben Chengba4fc8b2009-06-01 13:00:29 -07001261 };
buzbee9f601a92011-02-11 17:48:20 -08001262#endif
Ben Cheng7a0bcd02010-01-22 16:45:45 -08001263
buzbee9f601a92011-02-11 17:48:20 -08001264 // Begin initialization
1265 self->cardTable = gDvm.biasedCardTableBase;
1266 self->interpSave.pInterpBreak = &gDvm.interpBreak;
1267#if defined(WITH_JIT)
1268 self->jitToInterpEntries = jitToInterpEntries;
1269 self->icRechainCount = PREDICTED_CHAIN_COUNTER_RECHAIN;
1270 self->pJitProfTable = gDvmJit.pProfTable;
1271 self->ppJitProfTable = &gDvmJit.pProfTable;
1272 self->jitThreshold = gDvmJit.threshold;
1273 self->pProfileCountdown = &gDvmJit.profileCountdown;
1274#endif
1275
1276}
1277
buzbeea7d59bb2011-02-24 09:38:17 -08001278/*
1279 * Inter-instruction handler invoked in between instruction interpretations
1280 * to handle exceptional events such as debugging housekeeping, instruction
1281 * count profiling, JIT trace building, etc.
1282 */
1283void dvmCheckInst(u2 *dPC, Thread* self)
1284{
1285 //TODO add debugger, profiler, JIT, etc. checks here
1286}
buzbee9f601a92011-02-11 17:48:20 -08001287
1288/*
1289 * Main interpreter loop entry point. Select "standard" or "debug"
1290 * interpreter and switch between them as required.
1291 *
1292 * This begins executing code at the start of "method". On exit, "pResult"
1293 * holds the return value of the method (or, if "method" returns NULL, it
1294 * holds an undefined value).
1295 *
1296 * The interpreted stack frame, which holds the method arguments, has
1297 * already been set up.
1298 */
1299void dvmInterpret(Thread* self, const Method* method, JValue* pResult)
1300{
1301 bool change;
1302 InterpSaveState interpSaveState;
1303#if defined(WITH_JIT)
1304 /* Target-specific save/restore */
1305 extern void dvmJitCalleeSave(double *saveArea);
1306 extern void dvmJitCalleeRestore(double *saveArea);
1307 double calleeSave[JIT_CALLEE_SAVE_DOUBLE_COUNT];
Ben Cheng7a2697d2010-06-07 13:44:23 -07001308 /*
1309 * If the previous VM left the code cache through single-stepping the
1310 * inJitCodeCache flag will be set when the VM is re-entered (for example,
1311 * in self-verification mode we single-step NEW_INSTANCE which may re-enter
1312 * the VM through findClassFromLoaderNoInit). Because of that, we cannot
1313 * assert that self->inJitCodeCache is NULL here.
1314 */
Ben Chengba4fc8b2009-06-01 13:00:29 -07001315#endif
1316
buzbee9f601a92011-02-11 17:48:20 -08001317 /*
1318 * Save interpreter state from previous activation, linking
1319 * new to last.
1320 */
1321 interpSaveState = self->interpSave;
1322 self->interpSave.prev = &interpSaveState;
1323#if defined(WITH_JIT)
1324 dvmJitCalleeSave(calleeSave);
1325#endif
1326
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001327
1328#if defined(WITH_TRACKREF_CHECKS)
buzbeeef5db622011-02-22 14:01:46 -08001329 self->interpSave.debugTrackedRefStart =
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001330 dvmReferenceTableEntries(&self->internalLocalRefTable);
1331#endif
buzbee9f601a92011-02-11 17:48:20 -08001332 self->debugIsMethodEntry = true;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001333#if defined(WITH_JIT)
buzbee9f601a92011-02-11 17:48:20 -08001334 dvmJitCalleeSave(calleeSave);
Ben Chenga4973592010-03-31 11:59:18 -07001335 /* Initialize the state to kJitNot */
buzbee9f601a92011-02-11 17:48:20 -08001336 self->jitState = kJitNot;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001337#endif
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001338
1339 /*
1340 * Initialize working state.
1341 *
1342 * No need to initialize "retval".
1343 */
buzbee9f601a92011-02-11 17:48:20 -08001344 self->interpSave.method = method;
1345 self->interpSave.fp = (u4*) self->curFrame;
1346 self->interpSave.pc = method->insns;
1347 self->entryPoint = kInterpEntryInstr;
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001348
1349 if (dvmDebuggerOrProfilerActive())
buzbee9f601a92011-02-11 17:48:20 -08001350 self->nextMode = INTERP_DBG;
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001351 else
buzbee9f601a92011-02-11 17:48:20 -08001352 self->nextMode = INTERP_STD;
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001353
1354 assert(!dvmIsNativeMethod(method));
1355
1356 /*
1357 * Make sure the class is ready to go. Shouldn't be possible to get
1358 * here otherwise.
1359 */
1360 if (method->clazz->status < CLASS_INITIALIZING ||
1361 method->clazz->status == CLASS_ERROR)
1362 {
1363 LOGE("ERROR: tried to execute code in unprepared class '%s' (%d)\n",
1364 method->clazz->descriptor, method->clazz->status);
1365 dvmDumpThread(self, false);
1366 dvmAbort();
1367 }
1368
buzbee9f601a92011-02-11 17:48:20 -08001369 typedef bool (*Interpreter)(Thread*);
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001370 Interpreter stdInterp;
1371 if (gDvm.executionMode == kExecutionModeInterpFast)
1372 stdInterp = dvmMterpStd;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001373#if defined(WITH_JIT)
1374 else if (gDvm.executionMode == kExecutionModeJit)
1375/* If profiling overhead can be kept low enough, we can use a profiling
1376 * mterp fast for both Jit and "fast" modes. If overhead is too high,
1377 * create a specialized profiling interpreter.
1378 */
1379 stdInterp = dvmMterpStd;
1380#endif
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001381 else
1382 stdInterp = dvmInterpretStd;
1383
1384 change = true;
1385 while (change) {
buzbee9f601a92011-02-11 17:48:20 -08001386 switch (self->nextMode) {
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001387 case INTERP_STD:
1388 LOGVV("threadid=%d: interp STD\n", self->threadId);
buzbee9f601a92011-02-11 17:48:20 -08001389 change = (*stdInterp)(self);
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001390 break;
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001391 case INTERP_DBG:
1392 LOGVV("threadid=%d: interp DBG\n", self->threadId);
buzbee9f601a92011-02-11 17:48:20 -08001393 change = dvmInterpretDbg(self);
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001394 break;
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001395 default:
1396 dvmAbort();
1397 }
1398 }
1399
buzbee9f601a92011-02-11 17:48:20 -08001400 *pResult = self->retval;
1401
1402 /* Restore interpreter state from previous activation */
1403 self->interpSave = interpSaveState;
Bill Buzbee342806d2009-12-08 12:37:13 -08001404#if defined(WITH_JIT)
buzbee9f601a92011-02-11 17:48:20 -08001405 dvmJitCalleeRestore(calleeSave);
Bill Buzbee342806d2009-12-08 12:37:13 -08001406#endif
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001407}