blob: d3de7305b0c0fffd9a0378320243961d147fb5a7 [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 *
24 * Some debugger support functions are included here. Ideally their
25 * entire existence would be "#ifdef WITH_DEBUGGER", but we're not that
26 * aggressive in other parts of the code yet.
27 */
28#include "Dalvik.h"
29#include "interp/InterpDefs.h"
30
31
32/*
33 * ===========================================================================
34 * Debugger support
35 * ===========================================================================
36 */
37
Andy McFadden96516932009-10-28 17:39:02 -070038// fwd
39static BreakpointSet* dvmBreakpointSetAlloc(void);
40static void dvmBreakpointSetFree(BreakpointSet* pSet);
41
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -070042/*
Andy McFadden96516932009-10-28 17:39:02 -070043 * Initialize global breakpoint structures.
44 */
45bool dvmBreakpointStartup(void)
46{
47#ifdef WITH_DEBUGGER
48 gDvm.breakpointSet = dvmBreakpointSetAlloc();
49 return (gDvm.breakpointSet != NULL);
50#else
51 return true;
52#endif
53}
54
55/*
56 * Free resources.
57 */
58void dvmBreakpointShutdown(void)
59{
60#ifdef WITH_DEBUGGER
61 dvmBreakpointSetFree(gDvm.breakpointSet);
62#endif
63}
64
65
66#ifdef WITH_DEBUGGER
67/*
68 * This represents a breakpoint inserted in the instruction stream.
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -070069 *
Andy McFadden96516932009-10-28 17:39:02 -070070 * The debugger may ask us to create the same breakpoint multiple times.
71 * We only remove the breakpoint when the last instance is cleared.
72 */
73typedef struct {
Andy McFaddend22748a2010-04-22 17:08:11 -070074 Method* method; /* method we're associated with */
Andy McFadden96516932009-10-28 17:39:02 -070075 u2* addr; /* absolute memory address */
76 u1 originalOpCode; /* original 8-bit opcode value */
77 int setCount; /* #of times this breakpoint was set */
78} Breakpoint;
79
80/*
81 * Set of breakpoints.
82 */
83struct BreakpointSet {
84 /* grab lock before reading or writing anything else in here */
85 pthread_mutex_t lock;
86
87 /* vector of breakpoint structures */
88 int alloc;
89 int count;
90 Breakpoint* breakpoints;
91};
92
93/*
94 * Initialize a BreakpointSet. Initially empty.
95 */
96static BreakpointSet* dvmBreakpointSetAlloc(void)
97{
98 BreakpointSet* pSet = (BreakpointSet*) calloc(1, sizeof(*pSet));
99
100 dvmInitMutex(&pSet->lock);
101 /* leave the rest zeroed -- will alloc on first use */
102
103 return pSet;
104}
105
106/*
107 * Free storage associated with a BreakpointSet.
108 */
109static void dvmBreakpointSetFree(BreakpointSet* pSet)
110{
111 if (pSet == NULL)
112 return;
113
114 free(pSet->breakpoints);
115 free(pSet);
116}
117
118/*
119 * Lock the breakpoint set.
Andy McFaddend22748a2010-04-22 17:08:11 -0700120 *
121 * It's not currently necessary to switch to VMWAIT in the event of
122 * contention, because nothing in here can block. However, it's possible
123 * that the bytecode-updater code could become fancier in the future, so
124 * we do the trylock dance as a bit of future-proofing.
Andy McFadden96516932009-10-28 17:39:02 -0700125 */
126static void dvmBreakpointSetLock(BreakpointSet* pSet)
127{
Andy McFaddend22748a2010-04-22 17:08:11 -0700128 if (dvmTryLockMutex(&pSet->lock) != 0) {
129 Thread* self = dvmThreadSelf();
Carl Shapiro5617ad32010-07-02 10:50:57 -0700130 ThreadStatus oldStatus = dvmChangeStatus(self, THREAD_VMWAIT);
Andy McFaddend22748a2010-04-22 17:08:11 -0700131 dvmLockMutex(&pSet->lock);
132 dvmChangeStatus(self, oldStatus);
133 }
Andy McFadden96516932009-10-28 17:39:02 -0700134}
135
136/*
137 * Unlock the breakpoint set.
138 */
139static void dvmBreakpointSetUnlock(BreakpointSet* pSet)
140{
141 dvmUnlockMutex(&pSet->lock);
142}
143
144/*
145 * Return the #of breakpoints.
146 */
147static int dvmBreakpointSetCount(const BreakpointSet* pSet)
148{
149 return pSet->count;
150}
151
152/*
153 * See if we already have an entry for this address.
154 *
155 * The BreakpointSet's lock must be acquired before calling here.
156 *
157 * Returns the index of the breakpoint entry, or -1 if not found.
158 */
159static int dvmBreakpointSetFind(const BreakpointSet* pSet, const u2* addr)
160{
161 int i;
162
163 for (i = 0; i < pSet->count; i++) {
164 Breakpoint* pBreak = &pSet->breakpoints[i];
165 if (pBreak->addr == addr)
166 return i;
167 }
168
169 return -1;
170}
171
172/*
173 * Retrieve the opcode that was originally at the specified location.
174 *
175 * The BreakpointSet's lock must be acquired before calling here.
176 *
177 * Returns "true" with the opcode in *pOrig on success.
178 */
179static bool dvmBreakpointSetOriginalOpCode(const BreakpointSet* pSet,
180 const u2* addr, u1* pOrig)
181{
182 int idx = dvmBreakpointSetFind(pSet, addr);
183 if (idx < 0)
184 return false;
185
186 *pOrig = pSet->breakpoints[idx].originalOpCode;
187 return true;
188}
189
190/*
Andy McFaddenda9dc842010-05-03 16:11:20 -0700191 * Check the opcode. If it's a "magic" NOP, indicating the start of
192 * switch or array data in the instruction stream, we don't want to set
193 * a breakpoint.
194 *
195 * This can happen because the line number information dx generates
196 * associates the switch data with the switch statement's line number,
197 * and some debuggers put breakpoints at every address associated with
198 * a given line. The result is that the breakpoint stomps on the NOP
199 * instruction that doubles as a data table magic number, and an explicit
200 * check in the interpreter results in an exception being thrown.
201 *
202 * We don't want to simply refuse to add the breakpoint to the table,
203 * because that confuses the housekeeping. We don't want to reject the
204 * debugger's event request, and we want to be sure that there's exactly
205 * one un-set operation for every set op.
206 */
207static bool instructionIsMagicNop(const u2* addr)
208{
209 u2 curVal = *addr;
210 return ((curVal & 0xff) == OP_NOP && (curVal >> 8) != 0);
211}
212
213/*
Andy McFadden96516932009-10-28 17:39:02 -0700214 * Add a breakpoint at a specific address. If the address is already
215 * present in the table, this just increments the count.
216 *
217 * For a new entry, this will extract and preserve the current opcode from
218 * the instruction stream, and replace it with a breakpoint opcode.
219 *
220 * The BreakpointSet's lock must be acquired before calling here.
221 *
222 * Returns "true" on success.
223 */
224static bool dvmBreakpointSetAdd(BreakpointSet* pSet, Method* method,
225 unsigned int instrOffset)
226{
227 const int kBreakpointGrowth = 10;
228 const u2* addr = method->insns + instrOffset;
229 int idx = dvmBreakpointSetFind(pSet, addr);
230 Breakpoint* pBreak;
231
232 if (idx < 0) {
233 if (pSet->count == pSet->alloc) {
234 int newSize = pSet->alloc + kBreakpointGrowth;
235 Breakpoint* newVec;
236
237 LOGV("+++ increasing breakpoint set size to %d\n", newSize);
238
239 /* pSet->breakpoints will be NULL on first entry */
240 newVec = realloc(pSet->breakpoints, newSize * sizeof(Breakpoint));
241 if (newVec == NULL)
242 return false;
243
244 pSet->breakpoints = newVec;
245 pSet->alloc = newSize;
246 }
247
248 pBreak = &pSet->breakpoints[pSet->count++];
Andy McFaddend22748a2010-04-22 17:08:11 -0700249 pBreak->method = method;
Andy McFadden96516932009-10-28 17:39:02 -0700250 pBreak->addr = (u2*)addr;
251 pBreak->originalOpCode = *(u1*)addr;
252 pBreak->setCount = 1;
253
254 /*
255 * Change the opcode. We must ensure that the BreakpointSet
256 * updates happen before we change the opcode.
Andy McFaddend22748a2010-04-22 17:08:11 -0700257 *
258 * If the method has not been verified, we do NOT insert the
259 * breakpoint yet, since that will screw up the verifier. The
260 * debugger is allowed to insert breakpoints in unverified code,
261 * but since we don't execute unverified code we don't need to
262 * alter the bytecode yet.
263 *
Andy McFaddenc7a12b22010-04-30 10:08:55 -0700264 * The class init code will "flush" all pending opcode writes
265 * before verification completes.
Andy McFadden96516932009-10-28 17:39:02 -0700266 */
Andy McFadden96516932009-10-28 17:39:02 -0700267 assert(*(u1*)addr != OP_BREAKPOINT);
Andy McFaddend22748a2010-04-22 17:08:11 -0700268 if (dvmIsClassVerified(method->clazz)) {
269 LOGV("Class %s verified, adding breakpoint at %p\n",
270 method->clazz->descriptor, addr);
Andy McFaddenda9dc842010-05-03 16:11:20 -0700271 if (instructionIsMagicNop(addr)) {
272 LOGV("Refusing to set breakpoint on %04x at %s.%s + 0x%x\n",
273 *addr, method->clazz->descriptor, method->name,
274 instrOffset);
275 } else {
Andy McFadden6e10b9a2010-06-14 15:24:39 -0700276 ANDROID_MEMBAR_FULL();
Andy McFaddenda9dc842010-05-03 16:11:20 -0700277 dvmDexChangeDex1(method->clazz->pDvmDex, (u1*)addr,
278 OP_BREAKPOINT);
279 }
Andy McFaddend22748a2010-04-22 17:08:11 -0700280 } else {
281 LOGV("Class %s NOT verified, deferring breakpoint at %p\n",
282 method->clazz->descriptor, addr);
283 }
Andy McFadden96516932009-10-28 17:39:02 -0700284 } else {
Andy McFaddenc7a12b22010-04-30 10:08:55 -0700285 /*
286 * Breakpoint already exists, just increase the count.
287 */
Andy McFadden96516932009-10-28 17:39:02 -0700288 pBreak = &pSet->breakpoints[idx];
289 pBreak->setCount++;
Andy McFadden96516932009-10-28 17:39:02 -0700290 }
291
292 return true;
293}
294
295/*
296 * Remove one instance of the specified breakpoint. When the count
297 * reaches zero, the entry is removed from the table, and the original
298 * opcode is restored.
299 *
300 * The BreakpointSet's lock must be acquired before calling here.
301 */
302static void dvmBreakpointSetRemove(BreakpointSet* pSet, Method* method,
303 unsigned int instrOffset)
304{
305 const u2* addr = method->insns + instrOffset;
306 int idx = dvmBreakpointSetFind(pSet, addr);
307
308 if (idx < 0) {
309 /* breakpoint not found in set -- unexpected */
310 if (*(u1*)addr == OP_BREAKPOINT) {
Andy McFaddenda9dc842010-05-03 16:11:20 -0700311 LOGE("Unable to restore breakpoint opcode (%s.%s +0x%x)\n",
Andy McFadden96516932009-10-28 17:39:02 -0700312 method->clazz->descriptor, method->name, instrOffset);
313 dvmAbort();
314 } else {
Andy McFaddenda9dc842010-05-03 16:11:20 -0700315 LOGW("Breakpoint was already restored? (%s.%s +0x%x)\n",
Andy McFadden96516932009-10-28 17:39:02 -0700316 method->clazz->descriptor, method->name, instrOffset);
317 }
318 } else {
319 Breakpoint* pBreak = &pSet->breakpoints[idx];
320 if (pBreak->setCount == 1) {
321 /*
322 * Must restore opcode before removing set entry.
Andy McFaddend22748a2010-04-22 17:08:11 -0700323 *
324 * If the breakpoint was never flushed, we could be ovewriting
325 * a value with the same value. Not a problem, though we
326 * could end up causing a copy-on-write here when we didn't
327 * need to. (Not worth worrying about.)
Andy McFadden96516932009-10-28 17:39:02 -0700328 */
329 dvmDexChangeDex1(method->clazz->pDvmDex, (u1*)addr,
330 pBreak->originalOpCode);
Andy McFadden6e10b9a2010-06-14 15:24:39 -0700331 ANDROID_MEMBAR_FULL();
Andy McFadden96516932009-10-28 17:39:02 -0700332
333 if (idx != pSet->count-1) {
334 /* shift down */
335 memmove(&pSet->breakpoints[idx], &pSet->breakpoints[idx+1],
336 (pSet->count-1 - idx) * sizeof(pSet->breakpoints[0]));
337 }
338 pSet->count--;
339 pSet->breakpoints[pSet->count].addr = (u2*) 0xdecadead; // debug
340 } else {
341 pBreak->setCount--;
342 assert(pBreak->setCount > 0);
343 }
344 }
345}
346
347/*
Andy McFaddend22748a2010-04-22 17:08:11 -0700348 * Flush any breakpoints associated with methods in "clazz". We want to
349 * change the opcode, which might not have happened when the breakpoint
350 * was initially set because the class was in the process of being
351 * verified.
Andy McFadden96516932009-10-28 17:39:02 -0700352 *
353 * The BreakpointSet's lock must be acquired before calling here.
354 */
Andy McFaddend22748a2010-04-22 17:08:11 -0700355static void dvmBreakpointSetFlush(BreakpointSet* pSet, ClassObject* clazz)
Andy McFadden96516932009-10-28 17:39:02 -0700356{
Andy McFadden96516932009-10-28 17:39:02 -0700357 int i;
358 for (i = 0; i < pSet->count; i++) {
359 Breakpoint* pBreak = &pSet->breakpoints[i];
Andy McFaddend22748a2010-04-22 17:08:11 -0700360 if (pBreak->method->clazz == clazz) {
361 /*
362 * The breakpoint is associated with a method in this class.
363 * It might already be there or it might not; either way,
364 * flush it out.
365 */
366 LOGV("Flushing breakpoint at %p for %s\n",
367 pBreak->addr, clazz->descriptor);
Andy McFaddenda9dc842010-05-03 16:11:20 -0700368 if (instructionIsMagicNop(pBreak->addr)) {
Andy McFaddenda9dc842010-05-03 16:11:20 -0700369 LOGV("Refusing to flush breakpoint on %04x at %s.%s + 0x%x\n",
Carl Shapiroe3c01da2010-05-20 22:54:18 -0700370 *pBreak->addr, pBreak->method->clazz->descriptor,
371 pBreak->method->name, pBreak->addr - pBreak->method->insns);
Andy McFaddenda9dc842010-05-03 16:11:20 -0700372 } else {
373 dvmDexChangeDex1(clazz->pDvmDex, (u1*)pBreak->addr,
374 OP_BREAKPOINT);
375 }
Andy McFadden96516932009-10-28 17:39:02 -0700376 }
377 }
378}
Andy McFadden96516932009-10-28 17:39:02 -0700379#endif /*WITH_DEBUGGER*/
380
381
382/*
383 * Do any debugger-attach-time initialization.
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700384 */
385void dvmInitBreakpoints(void)
386{
387#ifdef WITH_DEBUGGER
Andy McFadden96516932009-10-28 17:39:02 -0700388 /* quick sanity check */
389 BreakpointSet* pSet = gDvm.breakpointSet;
390 dvmBreakpointSetLock(pSet);
391 if (dvmBreakpointSetCount(pSet) != 0) {
392 LOGW("WARNING: %d leftover breakpoints\n", dvmBreakpointSetCount(pSet));
393 /* generally not good, but we can keep going */
394 }
395 dvmBreakpointSetUnlock(pSet);
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700396#else
397 assert(false);
398#endif
399}
400
401/*
402 * Add an address to the list, putting it in the first non-empty slot.
403 *
404 * Sometimes the debugger likes to add two entries for one breakpoint.
405 * We add two entries here, so that we get the right behavior when it's
406 * removed twice.
407 *
408 * This will only be run from the JDWP thread, and it will happen while
409 * we are updating the event list, which is synchronized. We're guaranteed
410 * to be the only one adding entries, and the lock ensures that nobody
411 * will be trying to remove them while we're in here.
412 *
413 * "addr" is the absolute address of the breakpoint bytecode.
414 */
Andy McFadden96516932009-10-28 17:39:02 -0700415void dvmAddBreakAddr(Method* method, unsigned int instrOffset)
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700416{
417#ifdef WITH_DEBUGGER
Andy McFadden96516932009-10-28 17:39:02 -0700418 BreakpointSet* pSet = gDvm.breakpointSet;
419 dvmBreakpointSetLock(pSet);
420 dvmBreakpointSetAdd(pSet, method, instrOffset);
421 dvmBreakpointSetUnlock(pSet);
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700422#else
423 assert(false);
424#endif
425}
426
427/*
428 * Remove an address from the list by setting the entry to NULL.
429 *
430 * This can be called from the JDWP thread (because the debugger has
431 * cancelled the breakpoint) or from an event thread (because it's a
432 * single-shot breakpoint, e.g. "run to line"). We only get here as
433 * the result of removing an entry from the event list, which is
434 * synchronized, so it should not be possible for two threads to be
435 * updating breakpoints at the same time.
436 */
Andy McFadden96516932009-10-28 17:39:02 -0700437void dvmClearBreakAddr(Method* method, unsigned int instrOffset)
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700438{
439#ifdef WITH_DEBUGGER
Andy McFadden96516932009-10-28 17:39:02 -0700440 BreakpointSet* pSet = gDvm.breakpointSet;
441 dvmBreakpointSetLock(pSet);
442 dvmBreakpointSetRemove(pSet, method, instrOffset);
443 dvmBreakpointSetUnlock(pSet);
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700444
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700445#else
446 assert(false);
447#endif
448}
449
Andy McFadden96516932009-10-28 17:39:02 -0700450#ifdef WITH_DEBUGGER
451/*
452 * Get the original opcode from under a breakpoint.
Andy McFaddenfc3d3162010-08-05 14:34:26 -0700453 *
454 * On SMP hardware it's possible one core might try to execute a breakpoint
455 * after another core has cleared it. We need to handle the case where
456 * there's no entry in the breakpoint set. (The memory barriers in the
457 * locks and in the breakpoint update code should ensure that, once we've
458 * observed the absence of a breakpoint entry, we will also now observe
459 * the restoration of the original opcode. The fact that we're holding
460 * the lock prevents other threads from confusing things further.)
Andy McFadden96516932009-10-28 17:39:02 -0700461 */
462u1 dvmGetOriginalOpCode(const u2* addr)
463{
464 BreakpointSet* pSet = gDvm.breakpointSet;
465 u1 orig = 0;
466
467 dvmBreakpointSetLock(pSet);
468 if (!dvmBreakpointSetOriginalOpCode(pSet, addr, &orig)) {
469 orig = *(u1*)addr;
470 if (orig == OP_BREAKPOINT) {
471 LOGE("GLITCH: can't find breakpoint, opcode is still set\n");
472 dvmAbort();
473 }
474 }
475 dvmBreakpointSetUnlock(pSet);
476
477 return orig;
478}
479
480/*
Andy McFaddend22748a2010-04-22 17:08:11 -0700481 * Flush any breakpoints associated with methods in "clazz".
Andy McFadden96516932009-10-28 17:39:02 -0700482 *
Andy McFaddend22748a2010-04-22 17:08:11 -0700483 * We don't want to modify the bytecode of a method before the verifier
484 * gets a chance to look at it, so we postpone opcode replacement until
485 * after verification completes.
Andy McFadden96516932009-10-28 17:39:02 -0700486 */
Andy McFaddend22748a2010-04-22 17:08:11 -0700487void dvmFlushBreakpoints(ClassObject* clazz)
Andy McFadden96516932009-10-28 17:39:02 -0700488{
489 BreakpointSet* pSet = gDvm.breakpointSet;
490
Andy McFaddend22748a2010-04-22 17:08:11 -0700491 if (pSet == NULL)
492 return;
493
494 assert(dvmIsClassVerified(clazz));
Andy McFadden96516932009-10-28 17:39:02 -0700495 dvmBreakpointSetLock(pSet);
Andy McFaddend22748a2010-04-22 17:08:11 -0700496 dvmBreakpointSetFlush(pSet, clazz);
Andy McFadden96516932009-10-28 17:39:02 -0700497 dvmBreakpointSetUnlock(pSet);
498}
499#endif
500
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700501/*
502 * Add a single step event. Currently this is a global item.
503 *
504 * We set up some initial values based on the thread's current state. This
505 * won't work well if the thread is running, so it's up to the caller to
506 * verify that it's suspended.
507 *
508 * This is only called from the JDWP thread.
509 */
510bool dvmAddSingleStep(Thread* thread, int size, int depth)
511{
512#ifdef WITH_DEBUGGER
513 StepControl* pCtrl = &gDvm.stepControl;
514
515 if (pCtrl->active && thread != pCtrl->thread) {
516 LOGW("WARNING: single-step active for %p; adding %p\n",
517 pCtrl->thread, thread);
518
519 /*
520 * Keep going, overwriting previous. This can happen if you
521 * suspend a thread in Object.wait, hit the single-step key, then
522 * switch to another thread and do the same thing again.
523 * The first thread's step is still pending.
524 *
525 * TODO: consider making single-step per-thread. Adds to the
526 * overhead, but could be useful in rare situations.
527 */
528 }
529
530 pCtrl->size = size;
531 pCtrl->depth = depth;
532 pCtrl->thread = thread;
533
534 /*
535 * We may be stepping into or over method calls, or running until we
536 * return from the current method. To make this work we need to track
537 * the current line, current method, and current stack depth. We need
538 * to be checking these after most instructions, notably those that
539 * call methods, return from methods, or are on a different line from the
540 * previous instruction.
541 *
542 * We have to start with a snapshot of the current state. If we're in
543 * an interpreted method, everything we need is in the current frame. If
544 * we're in a native method, possibly with some extra JNI frames pushed
545 * on by PushLocalFrame, we want to use the topmost native method.
546 */
547 const StackSaveArea* saveArea;
548 void* fp;
549 void* prevFp = NULL;
Ben Cheng38329f52009-07-07 14:19:20 -0700550
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700551 for (fp = thread->curFrame; fp != NULL; fp = saveArea->prevFrame) {
552 const Method* method;
553
554 saveArea = SAVEAREA_FROM_FP(fp);
555 method = saveArea->method;
556
557 if (!dvmIsBreakFrame(fp) && !dvmIsNativeMethod(method))
558 break;
559 prevFp = fp;
560 }
561 if (fp == NULL) {
562 LOGW("Unexpected: step req in native-only threadid=%d\n",
563 thread->threadId);
564 return false;
565 }
566 if (prevFp != NULL) {
567 /*
568 * First interpreted frame wasn't the one at the bottom. Break
569 * frames are only inserted when calling from native->interp, so we
570 * don't need to worry about one being here.
571 */
572 LOGV("##### init step while in native method\n");
573 fp = prevFp;
574 assert(!dvmIsBreakFrame(fp));
575 assert(dvmIsNativeMethod(SAVEAREA_FROM_FP(fp)->method));
576 saveArea = SAVEAREA_FROM_FP(fp);
577 }
578
579 /*
580 * Pull the goodies out. "xtra.currentPc" should be accurate since
581 * we update it on every instruction while the debugger is connected.
582 */
583 pCtrl->method = saveArea->method;
584 // Clear out any old address set
585 if (pCtrl->pAddressSet != NULL) {
586 // (discard const)
587 free((void *)pCtrl->pAddressSet);
588 pCtrl->pAddressSet = NULL;
589 }
590 if (dvmIsNativeMethod(pCtrl->method)) {
591 pCtrl->line = -1;
592 } else {
593 pCtrl->line = dvmLineNumFromPC(saveArea->method,
594 saveArea->xtra.currentPc - saveArea->method->insns);
Ben Cheng38329f52009-07-07 14:19:20 -0700595 pCtrl->pAddressSet
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700596 = dvmAddressSetForLine(saveArea->method, pCtrl->line);
597 }
598 pCtrl->frameDepth = dvmComputeVagueFrameDepth(thread, thread->curFrame);
599 pCtrl->active = true;
600
601 LOGV("##### step init: thread=%p meth=%p '%s' line=%d frameDepth=%d depth=%s size=%s\n",
602 pCtrl->thread, pCtrl->method, pCtrl->method->name,
603 pCtrl->line, pCtrl->frameDepth,
604 dvmJdwpStepDepthStr(pCtrl->depth),
605 dvmJdwpStepSizeStr(pCtrl->size));
606
607 return true;
608#else
609 assert(false);
610 return false;
611#endif
612}
613
614/*
615 * Disable a single step event.
616 */
617void dvmClearSingleStep(Thread* thread)
618{
619#ifdef WITH_DEBUGGER
620 UNUSED_PARAMETER(thread);
621
622 gDvm.stepControl.active = false;
623#else
624 assert(false);
625#endif
626}
627
628
629/*
630 * Recover the "this" pointer from the current interpreted method. "this"
631 * is always in "in0" for non-static methods.
632 *
633 * The "ins" start at (#of registers - #of ins). Note in0 != v0.
634 *
635 * This works because "dx" guarantees that it will work. It's probably
636 * fairly common to have a virtual method that doesn't use its "this"
637 * pointer, in which case we're potentially wasting a register. However,
638 * the debugger doesn't treat "this" as just another argument. For
639 * example, events (such as breakpoints) can be enabled for specific
640 * values of "this". There is also a separate StackFrame.ThisObject call
641 * in JDWP that is expected to work for any non-native non-static method.
642 *
643 * Because we need it when setting up debugger event filters, we want to
644 * be able to do this quickly.
645 */
646Object* dvmGetThisPtr(const Method* method, const u4* fp)
647{
648 if (dvmIsStaticMethod(method))
649 return NULL;
650 return (Object*)fp[method->registersSize - method->insSize];
651}
652
653
654#if defined(WITH_TRACKREF_CHECKS)
655/*
656 * Verify that all internally-tracked references have been released. If
657 * they haven't, print them and abort the VM.
658 *
659 * "debugTrackedRefStart" indicates how many refs were on the list when
660 * we were first invoked.
661 */
662void dvmInterpCheckTrackedRefs(Thread* self, const Method* method,
663 int debugTrackedRefStart)
664{
665 if (dvmReferenceTableEntries(&self->internalLocalRefTable)
666 != (size_t) debugTrackedRefStart)
667 {
668 char* desc;
669 Object** top;
670 int count;
671
672 count = dvmReferenceTableEntries(&self->internalLocalRefTable);
673
674 LOGE("TRACK: unreleased internal reference (prev=%d total=%d)\n",
675 debugTrackedRefStart, count);
676 desc = dexProtoCopyMethodDescriptor(&method->prototype);
677 LOGE(" current method is %s.%s %s\n", method->clazz->descriptor,
678 method->name, desc);
679 free(desc);
680 top = self->internalLocalRefTable.table + debugTrackedRefStart;
681 while (top < self->internalLocalRefTable.nextEntry) {
682 LOGE(" %p (%s)\n",
683 *top,
684 ((*top)->clazz != NULL) ? (*top)->clazz->descriptor : "");
685 top++;
686 }
687 dvmDumpThread(self, false);
688
689 dvmAbort();
690 }
691 //LOGI("TRACK OK\n");
692}
693#endif
694
695
696#ifdef LOG_INSTR
697/*
698 * Dump the v-registers. Sent to the ILOG log tag.
699 */
700void dvmDumpRegs(const Method* method, const u4* framePtr, bool inOnly)
701{
702 int i, localCount;
703
704 localCount = method->registersSize - method->insSize;
705
706 LOG(LOG_VERBOSE, LOG_TAG"i", "Registers (fp=%p):\n", framePtr);
707 for (i = method->registersSize-1; i >= 0; i--) {
708 if (i >= localCount) {
709 LOG(LOG_VERBOSE, LOG_TAG"i", " v%-2d in%-2d : 0x%08x\n",
710 i, i-localCount, framePtr[i]);
711 } else {
712 if (inOnly) {
713 LOG(LOG_VERBOSE, LOG_TAG"i", " [...]\n");
714 break;
715 }
716 const char* name = "";
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700717#if 0 // "locals" structure has changed -- need to rewrite this
Elliott Hughes8afa9df2010-07-07 14:47:25 -0700718 int j;
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700719 DexFile* pDexFile = method->clazz->pDexFile;
720 const DexCode* pDexCode = dvmGetMethodCode(method);
721 int localsSize = dexGetLocalsSize(pDexFile, pDexCode);
722 const DexLocal* locals = dvmDexGetLocals(pDexFile, pDexCode);
723 for (j = 0; j < localsSize, j++) {
724 if (locals[j].registerNum == (u4) i) {
725 name = dvmDexStringStr(locals[j].pName);
726 break;
727 }
728 }
729#endif
730 LOG(LOG_VERBOSE, LOG_TAG"i", " v%-2d : 0x%08x %s\n",
731 i, framePtr[i], name);
732 }
733 }
734}
735#endif
736
737
738/*
739 * ===========================================================================
740 * Entry point and general support functions
741 * ===========================================================================
742 */
743
Ben Cheng38329f52009-07-07 14:19:20 -0700744/*
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700745 * Construct an s4 from two consecutive half-words of switch data.
746 * This needs to check endianness because the DEX optimizer only swaps
747 * half-words in instruction stream.
748 *
749 * "switchData" must be 32-bit aligned.
750 */
751#if __BYTE_ORDER == __LITTLE_ENDIAN
752static inline s4 s4FromSwitchData(const void* switchData) {
753 return *(s4*) switchData;
754}
755#else
756static inline s4 s4FromSwitchData(const void* switchData) {
757 u2* data = switchData;
758 return data[0] | (((s4) data[1]) << 16);
Jay Freeman (saurik)ffa5c292008-11-16 13:51:51 +0000759}
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700760#endif
761
762/*
763 * Find the matching case. Returns the offset to the handler instructions.
764 *
765 * Returns 3 if we don't find a match (it's the size of the packed-switch
766 * instruction).
767 */
768s4 dvmInterpHandlePackedSwitch(const u2* switchData, s4 testVal)
769{
770 const int kInstrLen = 3;
771 u2 size;
772 s4 firstKey;
773 const s4* entries;
774
775 /*
776 * Packed switch data format:
777 * ushort ident = 0x0100 magic value
778 * ushort size number of entries in the table
779 * int first_key first (and lowest) switch case value
780 * int targets[size] branch targets, relative to switch opcode
781 *
782 * Total size is (4+size*2) 16-bit code units.
783 */
784 if (*switchData++ != kPackedSwitchSignature) {
785 /* should have been caught by verifier */
786 dvmThrowException("Ljava/lang/InternalError;",
787 "bad packed switch magic");
788 return kInstrLen;
789 }
790
791 size = *switchData++;
792 assert(size > 0);
793
794 firstKey = *switchData++;
795 firstKey |= (*switchData++) << 16;
796
797 if (testVal < firstKey || testVal >= firstKey + size) {
798 LOGVV("Value %d not found in switch (%d-%d)\n",
799 testVal, firstKey, firstKey+size-1);
800 return kInstrLen;
801 }
802
803 /* The entries are guaranteed to be aligned on a 32-bit boundary;
804 * we can treat them as a native int array.
805 */
806 entries = (const s4*) switchData;
807 assert(((u4)entries & 0x3) == 0);
808
809 assert(testVal - firstKey >= 0 && testVal - firstKey < size);
810 LOGVV("Value %d found in slot %d (goto 0x%02x)\n",
811 testVal, testVal - firstKey,
812 s4FromSwitchData(&entries[testVal - firstKey]));
813 return s4FromSwitchData(&entries[testVal - firstKey]);
814}
815
816/*
817 * Find the matching case. Returns the offset to the handler instructions.
818 *
819 * Returns 3 if we don't find a match (it's the size of the sparse-switch
820 * instruction).
821 */
822s4 dvmInterpHandleSparseSwitch(const u2* switchData, s4 testVal)
823{
824 const int kInstrLen = 3;
Carl Shapiroe3c01da2010-05-20 22:54:18 -0700825 u2 size;
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700826 const s4* keys;
827 const s4* entries;
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700828
829 /*
830 * Sparse switch data format:
831 * ushort ident = 0x0200 magic value
832 * ushort size number of entries in the table; > 0
833 * int keys[size] keys, sorted low-to-high; 32-bit aligned
834 * int targets[size] branch targets, relative to switch opcode
835 *
836 * Total size is (2+size*4) 16-bit code units.
837 */
838
839 if (*switchData++ != kSparseSwitchSignature) {
840 /* should have been caught by verifier */
841 dvmThrowException("Ljava/lang/InternalError;",
842 "bad sparse switch magic");
843 return kInstrLen;
844 }
845
846 size = *switchData++;
847 assert(size > 0);
Ben Cheng38329f52009-07-07 14:19:20 -0700848
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700849 /* The keys are guaranteed to be aligned on a 32-bit boundary;
850 * we can treat them as a native int array.
851 */
852 keys = (const s4*) switchData;
853 assert(((u4)keys & 0x3) == 0);
854
855 /* The entries are guaranteed to be aligned on a 32-bit boundary;
856 * we can treat them as a native int array.
857 */
858 entries = keys + size;
859 assert(((u4)entries & 0x3) == 0);
860
861 /*
Andy McFadden62f19152009-10-21 16:59:31 -0700862 * Binary-search through the array of keys, which are guaranteed to
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700863 * be sorted low-to-high.
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700864 */
Andy McFadden62f19152009-10-21 16:59:31 -0700865 int lo = 0;
866 int hi = size - 1;
867 while (lo <= hi) {
868 int mid = (lo + hi) >> 1;
869
870 s4 foundVal = s4FromSwitchData(&keys[mid]);
871 if (testVal < foundVal) {
872 hi = mid - 1;
873 } else if (testVal > foundVal) {
874 lo = mid + 1;
875 } else {
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700876 LOGVV("Value %d found in entry %d (goto 0x%02x)\n",
Andy McFadden62f19152009-10-21 16:59:31 -0700877 testVal, mid, s4FromSwitchData(&entries[mid]));
878 return s4FromSwitchData(&entries[mid]);
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700879 }
880 }
881
882 LOGVV("Value %d not found in switch\n", testVal);
883 return kInstrLen;
884}
885
886/*
Andy McFadden6f214502009-06-30 16:14:30 -0700887 * Copy data for a fill-array-data instruction. On a little-endian machine
888 * we can just do a memcpy(), on a big-endian system we have work to do.
889 *
890 * The trick here is that dexopt has byte-swapped each code unit, which is
891 * exactly what we want for short/char data. For byte data we need to undo
892 * the swap, and for 4- or 8-byte values we need to swap pieces within
893 * each word.
894 */
895static void copySwappedArrayData(void* dest, const u2* src, u4 size, u2 width)
896{
897#if __BYTE_ORDER == __LITTLE_ENDIAN
898 memcpy(dest, src, size*width);
899#else
900 int i;
901
902 switch (width) {
903 case 1:
904 /* un-swap pairs of bytes as we go */
905 for (i = (size-1) & ~1; i >= 0; i -= 2) {
906 ((u1*)dest)[i] = ((u1*)src)[i+1];
907 ((u1*)dest)[i+1] = ((u1*)src)[i];
908 }
909 /*
910 * "src" is padded to end on a two-byte boundary, but we don't want to
911 * assume "dest" is, so we handle odd length specially.
912 */
913 if ((size & 1) != 0) {
914 ((u1*)dest)[size-1] = ((u1*)src)[size];
915 }
916 break;
917 case 2:
918 /* already swapped correctly */
919 memcpy(dest, src, size*width);
920 break;
921 case 4:
922 /* swap word halves */
923 for (i = 0; i < (int) size; i++) {
924 ((u4*)dest)[i] = (src[(i << 1) + 1] << 16) | src[i << 1];
925 }
926 break;
927 case 8:
928 /* swap word halves and words */
929 for (i = 0; i < (int) (size << 1); i += 2) {
930 ((int*)dest)[i] = (src[(i << 1) + 3] << 16) | src[(i << 1) + 2];
931 ((int*)dest)[i+1] = (src[(i << 1) + 1] << 16) | src[i << 1];
932 }
933 break;
934 default:
935 LOGE("Unexpected width %d in copySwappedArrayData\n", width);
936 dvmAbort();
937 break;
938 }
939#endif
940}
941
942/*
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700943 * Fill the array with predefined constant values.
944 *
945 * Returns true if job is completed, otherwise false to indicate that
946 * an exception has been thrown.
947 */
The Android Open Source Project89c1feb2008-12-17 18:03:55 -0800948bool dvmInterpHandleFillArrayData(ArrayObject* arrayObj, const u2* arrayData)
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700949{
950 u2 width;
951 u4 size;
952
The Android Open Source Project89c1feb2008-12-17 18:03:55 -0800953 if (arrayObj == NULL) {
954 dvmThrowException("Ljava/lang/NullPointerException;", NULL);
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700955 return false;
956 }
Barry Hayes7dc96602010-02-24 09:19:07 -0800957 assert (!IS_CLASS_FLAG_SET(((Object *)arrayObj)->clazz,
958 CLASS_ISOBJECTARRAY));
The Android Open Source Project89c1feb2008-12-17 18:03:55 -0800959
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700960 /*
961 * Array data table format:
962 * ushort ident = 0x0300 magic value
963 * ushort width width of each element in the table
964 * uint size number of elements in the table
965 * ubyte data[size*width] table of data values (may contain a single-byte
966 * padding at the end)
967 *
968 * Total size is 4+(width * size + 1)/2 16-bit code units.
969 */
970 if (arrayData[0] != kArrayDataSignature) {
971 dvmThrowException("Ljava/lang/InternalError;", "bad array data magic");
972 return false;
973 }
974
975 width = arrayData[1];
976 size = arrayData[2] | (((u4)arrayData[3]) << 16);
977
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800978 if (size > arrayObj->length) {
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700979 dvmThrowException("Ljava/lang/ArrayIndexOutOfBoundsException;", NULL);
980 return false;
981 }
Andy McFadden6f214502009-06-30 16:14:30 -0700982 copySwappedArrayData(arrayObj->contents, &arrayData[4], size, width);
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700983 return true;
984}
985
986/*
987 * Find the concrete method that corresponds to "methodIdx". The code in
988 * "method" is executing invoke-method with "thisClass" as its first argument.
989 *
990 * Returns NULL with an exception raised on failure.
991 */
992Method* dvmInterpFindInterfaceMethod(ClassObject* thisClass, u4 methodIdx,
993 const Method* method, DvmDex* methodClassDex)
994{
995 Method* absMethod;
996 Method* methodToCall;
997 int i, vtableIndex;
998
999 /*
1000 * Resolve the method. This gives us the abstract method from the
1001 * interface class declaration.
1002 */
1003 absMethod = dvmDexGetResolvedMethod(methodClassDex, methodIdx);
1004 if (absMethod == NULL) {
1005 absMethod = dvmResolveInterfaceMethod(method->clazz, methodIdx);
1006 if (absMethod == NULL) {
1007 LOGV("+ unknown method\n");
1008 return NULL;
1009 }
1010 }
1011
1012 /* make sure absMethod->methodIndex means what we think it means */
1013 assert(dvmIsAbstractMethod(absMethod));
1014
1015 /*
1016 * Run through the "this" object's iftable. Find the entry for
1017 * absMethod's class, then use absMethod->methodIndex to find
1018 * the method's entry. The value there is the offset into our
1019 * vtable of the actual method to execute.
1020 *
1021 * The verifier does not guarantee that objects stored into
1022 * interface references actually implement the interface, so this
1023 * check cannot be eliminated.
1024 */
1025 for (i = 0; i < thisClass->iftableCount; i++) {
1026 if (thisClass->iftable[i].clazz == absMethod->clazz)
1027 break;
1028 }
1029 if (i == thisClass->iftableCount) {
1030 /* impossible in verified DEX, need to check for it in unverified */
1031 dvmThrowException("Ljava/lang/IncompatibleClassChangeError;",
1032 "interface not implemented");
1033 return NULL;
1034 }
1035
1036 assert(absMethod->methodIndex <
1037 thisClass->iftable[i].clazz->virtualMethodCount);
1038
1039 vtableIndex =
1040 thisClass->iftable[i].methodIndexArray[absMethod->methodIndex];
1041 assert(vtableIndex >= 0 && vtableIndex < thisClass->vtableCount);
1042 methodToCall = thisClass->vtable[vtableIndex];
1043
1044#if 0
1045 /* this can happen when there's a stale class file */
1046 if (dvmIsAbstractMethod(methodToCall)) {
1047 dvmThrowException("Ljava/lang/AbstractMethodError;",
1048 "interface method not implemented");
1049 return NULL;
1050 }
1051#else
1052 assert(!dvmIsAbstractMethod(methodToCall) ||
1053 methodToCall->nativeFunc != NULL);
1054#endif
1055
1056 LOGVV("+++ interface=%s.%s concrete=%s.%s\n",
1057 absMethod->clazz->descriptor, absMethod->name,
1058 methodToCall->clazz->descriptor, methodToCall->name);
1059 assert(methodToCall != NULL);
1060
1061 return methodToCall;
1062}
1063
1064
Andy McFaddenb51ea112009-05-08 16:50:17 -07001065
1066/*
1067 * Helpers for dvmThrowVerificationError().
1068 *
1069 * Each returns a newly-allocated string.
1070 */
1071#define kThrowShow_accessFromClass 1
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001072static char* classNameFromIndex(const Method* method, int ref,
1073 VerifyErrorRefType refType, int flags)
Andy McFaddenb51ea112009-05-08 16:50:17 -07001074{
1075 static const int kBufLen = 256;
1076 const DvmDex* pDvmDex = method->clazz->pDvmDex;
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001077
1078 if (refType == VERIFY_ERROR_REF_FIELD) {
1079 /* get class ID from field ID */
1080 const DexFieldId* pFieldId = dexGetFieldId(pDvmDex->pDexFile, ref);
1081 ref = pFieldId->classIdx;
1082 } else if (refType == VERIFY_ERROR_REF_METHOD) {
1083 /* get class ID from method ID */
1084 const DexMethodId* pMethodId = dexGetMethodId(pDvmDex->pDexFile, ref);
1085 ref = pMethodId->classIdx;
1086 }
1087
Andy McFaddenb51ea112009-05-08 16:50:17 -07001088 const char* className = dexStringByTypeIdx(pDvmDex->pDexFile, ref);
1089 char* dotClassName = dvmDescriptorToDot(className);
1090 if (flags == 0)
1091 return dotClassName;
1092
1093 char* result = (char*) malloc(kBufLen);
1094
1095 if ((flags & kThrowShow_accessFromClass) != 0) {
1096 char* dotFromName = dvmDescriptorToDot(method->clazz->descriptor);
1097 snprintf(result, kBufLen, "tried to access class %s from class %s",
1098 dotClassName, dotFromName);
1099 free(dotFromName);
1100 } else {
1101 assert(false); // should've been caught above
1102 result[0] = '\0';
1103 }
1104
1105 free(dotClassName);
1106 return result;
1107}
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001108static char* fieldNameFromIndex(const Method* method, int ref,
1109 VerifyErrorRefType refType, int flags)
Andy McFaddenb51ea112009-05-08 16:50:17 -07001110{
1111 static const int kBufLen = 256;
1112 const DvmDex* pDvmDex = method->clazz->pDvmDex;
1113 const DexFieldId* pFieldId;
1114 const char* className;
1115 const char* fieldName;
1116
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001117 if (refType != VERIFY_ERROR_REF_FIELD) {
1118 LOGW("Expected ref type %d, got %d\n", VERIFY_ERROR_REF_FIELD, refType);
1119 return NULL; /* no message */
1120 }
1121
Andy McFaddenb51ea112009-05-08 16:50:17 -07001122 pFieldId = dexGetFieldId(pDvmDex->pDexFile, ref);
1123 className = dexStringByTypeIdx(pDvmDex->pDexFile, pFieldId->classIdx);
1124 fieldName = dexStringById(pDvmDex->pDexFile, pFieldId->nameIdx);
1125
1126 char* dotName = dvmDescriptorToDot(className);
1127 char* result = (char*) malloc(kBufLen);
1128
1129 if ((flags & kThrowShow_accessFromClass) != 0) {
1130 char* dotFromName = dvmDescriptorToDot(method->clazz->descriptor);
1131 snprintf(result, kBufLen, "tried to access field %s.%s from class %s",
1132 dotName, fieldName, dotFromName);
1133 free(dotFromName);
1134 } else {
1135 snprintf(result, kBufLen, "%s.%s", dotName, fieldName);
1136 }
1137
1138 free(dotName);
1139 return result;
1140}
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001141static char* methodNameFromIndex(const Method* method, int ref,
1142 VerifyErrorRefType refType, int flags)
Andy McFaddenb51ea112009-05-08 16:50:17 -07001143{
1144 static const int kBufLen = 384;
1145 const DvmDex* pDvmDex = method->clazz->pDvmDex;
1146 const DexMethodId* pMethodId;
1147 const char* className;
1148 const char* methodName;
1149
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001150 if (refType != VERIFY_ERROR_REF_METHOD) {
1151 LOGW("Expected ref type %d, got %d\n", VERIFY_ERROR_REF_METHOD,refType);
1152 return NULL; /* no message */
1153 }
1154
Andy McFaddenb51ea112009-05-08 16:50:17 -07001155 pMethodId = dexGetMethodId(pDvmDex->pDexFile, ref);
1156 className = dexStringByTypeIdx(pDvmDex->pDexFile, pMethodId->classIdx);
1157 methodName = dexStringById(pDvmDex->pDexFile, pMethodId->nameIdx);
1158
1159 char* dotName = dvmDescriptorToDot(className);
1160 char* result = (char*) malloc(kBufLen);
1161
1162 if ((flags & kThrowShow_accessFromClass) != 0) {
1163 char* dotFromName = dvmDescriptorToDot(method->clazz->descriptor);
1164 char* desc = dexProtoCopyMethodDescriptor(&method->prototype);
1165 snprintf(result, kBufLen,
1166 "tried to access method %s.%s:%s from class %s",
1167 dotName, methodName, desc, dotFromName);
1168 free(dotFromName);
1169 free(desc);
1170 } else {
1171 snprintf(result, kBufLen, "%s.%s", dotName, methodName);
1172 }
1173
1174 free(dotName);
1175 return result;
1176}
1177
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001178/*
Andy McFadden3a1aedb2009-05-07 13:30:23 -07001179 * Throw an exception for a problem identified by the verifier.
1180 *
1181 * This is used by the invoke-verification-error instruction. It always
1182 * throws an exception.
1183 *
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001184 * "kind" indicates the kind of failure encountered by the verifier. It
1185 * has two parts, an error code and an indication of the reference type.
Andy McFadden3a1aedb2009-05-07 13:30:23 -07001186 */
Andy McFaddenb51ea112009-05-08 16:50:17 -07001187void dvmThrowVerificationError(const Method* method, int kind, int ref)
Andy McFadden3a1aedb2009-05-07 13:30:23 -07001188{
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001189 const int typeMask = 0xff << kVerifyErrorRefTypeShift;
1190 VerifyError errorKind = kind & ~typeMask;
1191 VerifyErrorRefType refType = kind >> kVerifyErrorRefTypeShift;
Andy McFaddenb51ea112009-05-08 16:50:17 -07001192 const char* exceptionName = "Ljava/lang/VerifyError;";
1193 char* msg = NULL;
1194
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001195 switch ((VerifyError) errorKind) {
Andy McFaddenb51ea112009-05-08 16:50:17 -07001196 case VERIFY_ERROR_NO_CLASS:
1197 exceptionName = "Ljava/lang/NoClassDefFoundError;";
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001198 msg = classNameFromIndex(method, ref, refType, 0);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001199 break;
1200 case VERIFY_ERROR_NO_FIELD:
1201 exceptionName = "Ljava/lang/NoSuchFieldError;";
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001202 msg = fieldNameFromIndex(method, ref, refType, 0);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001203 break;
1204 case VERIFY_ERROR_NO_METHOD:
1205 exceptionName = "Ljava/lang/NoSuchMethodError;";
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001206 msg = methodNameFromIndex(method, ref, refType, 0);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001207 break;
1208 case VERIFY_ERROR_ACCESS_CLASS:
1209 exceptionName = "Ljava/lang/IllegalAccessError;";
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001210 msg = classNameFromIndex(method, ref, refType,
1211 kThrowShow_accessFromClass);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001212 break;
1213 case VERIFY_ERROR_ACCESS_FIELD:
1214 exceptionName = "Ljava/lang/IllegalAccessError;";
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001215 msg = fieldNameFromIndex(method, ref, refType,
1216 kThrowShow_accessFromClass);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001217 break;
1218 case VERIFY_ERROR_ACCESS_METHOD:
1219 exceptionName = "Ljava/lang/IllegalAccessError;";
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001220 msg = methodNameFromIndex(method, ref, refType,
1221 kThrowShow_accessFromClass);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001222 break;
1223 case VERIFY_ERROR_CLASS_CHANGE:
1224 exceptionName = "Ljava/lang/IncompatibleClassChangeError;";
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001225 msg = classNameFromIndex(method, ref, refType, 0);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001226 break;
1227 case VERIFY_ERROR_INSTANTIATION:
1228 exceptionName = "Ljava/lang/InstantiationError;";
Andy McFaddenaf0e8382009-08-28 10:38:37 -07001229 msg = classNameFromIndex(method, ref, refType, 0);
Andy McFaddenb51ea112009-05-08 16:50:17 -07001230 break;
1231
1232 case VERIFY_ERROR_GENERIC:
1233 /* generic VerifyError; use default exception, no message */
1234 break;
1235 case VERIFY_ERROR_NONE:
1236 /* should never happen; use default exception */
1237 assert(false);
1238 msg = strdup("weird - no error specified");
1239 break;
1240
1241 /* no default clause -- want warning if enum updated */
1242 }
1243
1244 dvmThrowException(exceptionName, msg);
1245 free(msg);
Andy McFadden3a1aedb2009-05-07 13:30:23 -07001246}
1247
Andy McFadden3a1aedb2009-05-07 13:30:23 -07001248/*
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001249 * Main interpreter loop entry point. Select "standard" or "debug"
1250 * interpreter and switch between them as required.
1251 *
1252 * This begins executing code at the start of "method". On exit, "pResult"
1253 * holds the return value of the method (or, if "method" returns NULL, it
1254 * holds an undefined value).
1255 *
1256 * The interpreted stack frame, which holds the method arguments, has
1257 * already been set up.
1258 */
1259void dvmInterpret(Thread* self, const Method* method, JValue* pResult)
1260{
1261 InterpState interpState;
1262 bool change;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001263#if defined(WITH_JIT)
Bill Buzbee342806d2009-12-08 12:37:13 -08001264 /* Target-specific save/restore */
1265 extern void dvmJitCalleeSave(double *saveArea);
1266 extern void dvmJitCalleeRestore(double *saveArea);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001267 /* Interpreter entry points from compiled code */
1268 extern void dvmJitToInterpNormal();
1269 extern void dvmJitToInterpNoChain();
1270 extern void dvmJitToInterpPunt();
1271 extern void dvmJitToInterpSingleStep();
Ben Cheng40094c12010-02-24 20:58:44 -08001272 extern void dvmJitToInterpTraceSelectNoChain();
1273 extern void dvmJitToInterpTraceSelect();
Ben Cheng38329f52009-07-07 14:19:20 -07001274 extern void dvmJitToPatchPredictedChain();
Jeff Hao97319a82009-08-12 16:57:15 -07001275#if defined(WITH_SELF_VERIFICATION)
Ben Cheng40094c12010-02-24 20:58:44 -08001276 extern void dvmJitToInterpBackwardBranch();
Jeff Hao97319a82009-08-12 16:57:15 -07001277#endif
Ben Chengba4fc8b2009-06-01 13:00:29 -07001278
Ben Cheng38329f52009-07-07 14:19:20 -07001279 /*
Ben Chengba4fc8b2009-06-01 13:00:29 -07001280 * Reserve a static entity here to quickly setup runtime contents as
1281 * gcc will issue block copy instructions.
1282 */
1283 static struct JitToInterpEntries jitToInterpEntries = {
1284 dvmJitToInterpNormal,
1285 dvmJitToInterpNoChain,
1286 dvmJitToInterpPunt,
1287 dvmJitToInterpSingleStep,
Ben Cheng40094c12010-02-24 20:58:44 -08001288 dvmJitToInterpTraceSelectNoChain,
1289 dvmJitToInterpTraceSelect,
Ben Cheng38329f52009-07-07 14:19:20 -07001290 dvmJitToPatchPredictedChain,
Jeff Hao97319a82009-08-12 16:57:15 -07001291#if defined(WITH_SELF_VERIFICATION)
Ben Cheng40094c12010-02-24 20:58:44 -08001292 dvmJitToInterpBackwardBranch,
Jeff Hao97319a82009-08-12 16:57:15 -07001293#endif
Ben Chengba4fc8b2009-06-01 13:00:29 -07001294 };
Ben Cheng7a0bcd02010-01-22 16:45:45 -08001295
Ben Cheng7a2697d2010-06-07 13:44:23 -07001296 /*
1297 * If the previous VM left the code cache through single-stepping the
1298 * inJitCodeCache flag will be set when the VM is re-entered (for example,
1299 * in self-verification mode we single-step NEW_INSTANCE which may re-enter
1300 * the VM through findClassFromLoaderNoInit). Because of that, we cannot
1301 * assert that self->inJitCodeCache is NULL here.
1302 */
Ben Chengba4fc8b2009-06-01 13:00:29 -07001303#endif
1304
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001305
1306#if defined(WITH_TRACKREF_CHECKS)
1307 interpState.debugTrackedRefStart =
1308 dvmReferenceTableEntries(&self->internalLocalRefTable);
1309#endif
1310#if defined(WITH_PROFILER) || defined(WITH_DEBUGGER)
1311 interpState.debugIsMethodEntry = true;
1312#endif
Ben Chengba4fc8b2009-06-01 13:00:29 -07001313#if defined(WITH_JIT)
Bill Buzbee342806d2009-12-08 12:37:13 -08001314 dvmJitCalleeSave(interpState.calleeSave);
Ben Chenga4973592010-03-31 11:59:18 -07001315 /* Initialize the state to kJitNot */
1316 interpState.jitState = kJitNot;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001317
1318 /* Setup the Jit-to-interpreter entry points */
1319 interpState.jitToInterpEntries = jitToInterpEntries;
Bill Buzbee48f18242009-06-19 16:02:27 -07001320
1321 /*
1322 * Initialize the threshold filter [don't bother to zero out the
1323 * actual table. We're looking for matches, and an occasional
1324 * false positive is acceptible.
1325 */
1326 interpState.lastThreshFilter = 0;
Ben Chengb88ec3c2010-05-17 12:50:33 -07001327
1328 interpState.icRechainCount = PREDICTED_CHAIN_COUNTER_RECHAIN;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001329#endif
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001330
1331 /*
1332 * Initialize working state.
1333 *
1334 * No need to initialize "retval".
1335 */
1336 interpState.method = method;
1337 interpState.fp = (u4*) self->curFrame;
1338 interpState.pc = method->insns;
1339 interpState.entryPoint = kInterpEntryInstr;
1340
1341 if (dvmDebuggerOrProfilerActive())
1342 interpState.nextMode = INTERP_DBG;
1343 else
1344 interpState.nextMode = INTERP_STD;
1345
1346 assert(!dvmIsNativeMethod(method));
1347
1348 /*
1349 * Make sure the class is ready to go. Shouldn't be possible to get
1350 * here otherwise.
1351 */
1352 if (method->clazz->status < CLASS_INITIALIZING ||
1353 method->clazz->status == CLASS_ERROR)
1354 {
1355 LOGE("ERROR: tried to execute code in unprepared class '%s' (%d)\n",
1356 method->clazz->descriptor, method->clazz->status);
1357 dvmDumpThread(self, false);
1358 dvmAbort();
1359 }
1360
1361 typedef bool (*Interpreter)(Thread*, InterpState*);
1362 Interpreter stdInterp;
1363 if (gDvm.executionMode == kExecutionModeInterpFast)
1364 stdInterp = dvmMterpStd;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001365#if defined(WITH_JIT)
1366 else if (gDvm.executionMode == kExecutionModeJit)
1367/* If profiling overhead can be kept low enough, we can use a profiling
1368 * mterp fast for both Jit and "fast" modes. If overhead is too high,
1369 * create a specialized profiling interpreter.
1370 */
1371 stdInterp = dvmMterpStd;
1372#endif
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001373 else
1374 stdInterp = dvmInterpretStd;
1375
1376 change = true;
1377 while (change) {
1378 switch (interpState.nextMode) {
1379 case INTERP_STD:
1380 LOGVV("threadid=%d: interp STD\n", self->threadId);
1381 change = (*stdInterp)(self, &interpState);
1382 break;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001383#if defined(WITH_PROFILER) || defined(WITH_DEBUGGER) || defined(WITH_JIT)
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001384 case INTERP_DBG:
1385 LOGVV("threadid=%d: interp DBG\n", self->threadId);
1386 change = dvmInterpretDbg(self, &interpState);
1387 break;
1388#endif
1389 default:
1390 dvmAbort();
1391 }
1392 }
1393
Barry Hayes364f9d92010-06-11 16:12:47 -07001394 /* Never on the heap, so no write barrier needed. */
1395 assert(!dvmIsValidObjectAddress(pResult));
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001396 *pResult = interpState.retval;
Bill Buzbee342806d2009-12-08 12:37:13 -08001397#if defined(WITH_JIT)
1398 dvmJitCalleeRestore(interpState.calleeSave);
1399#endif
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -07001400}