blob: 260ef1502675945d038d5ce4a4a7ec05cc029ca5 [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 */
16/*
17 * Main interpreter entry point and support functions.
18 *
19 * The entry point selects the "standard" or "debug" interpreter and
20 * facilitates switching between them. The standard interpreter may
21 * use the "fast" or "portable" implementation.
22 *
23 * Some debugger support functions are included here. Ideally their
24 * entire existence would be "#ifdef WITH_DEBUGGER", but we're not that
25 * aggressive in other parts of the code yet.
26 */
27#include "Dalvik.h"
28#include "interp/InterpDefs.h"
29
30
31/*
32 * ===========================================================================
33 * Debugger support
34 * ===========================================================================
35 */
36
37/*
38 * Initialize the breakpoint address lookup table when the debugger attaches.
39 *
40 * This shouldn't be necessary -- the global area is initially zeroed out,
41 * and the events should be cleaning up after themselves.
42 */
43void dvmInitBreakpoints(void)
44{
45#ifdef WITH_DEBUGGER
46 memset(gDvm.debugBreakAddr, 0, sizeof(gDvm.debugBreakAddr));
47#else
48 assert(false);
49#endif
50}
51
52/*
53 * Add an address to the list, putting it in the first non-empty slot.
54 *
55 * Sometimes the debugger likes to add two entries for one breakpoint.
56 * We add two entries here, so that we get the right behavior when it's
57 * removed twice.
58 *
59 * This will only be run from the JDWP thread, and it will happen while
60 * we are updating the event list, which is synchronized. We're guaranteed
61 * to be the only one adding entries, and the lock ensures that nobody
62 * will be trying to remove them while we're in here.
63 *
64 * "addr" is the absolute address of the breakpoint bytecode.
65 */
66void dvmAddBreakAddr(Method* method, int instrOffset)
67{
68#ifdef WITH_DEBUGGER
69 const u2* addr = method->insns + instrOffset;
70 const u2** ptr = gDvm.debugBreakAddr;
71 int i;
72
73 LOGV("BKP: add %p %s.%s (%s:%d)\n",
74 addr, method->clazz->descriptor, method->name,
75 dvmGetMethodSourceFile(method), dvmLineNumFromPC(method, instrOffset));
76
77 method->debugBreakpointCount++;
78 for (i = 0; i < MAX_BREAKPOINTS; i++, ptr++) {
79 if (*ptr == NULL) {
80 *ptr = addr;
81 break;
82 }
83 }
84 if (i == MAX_BREAKPOINTS) {
85 /* no room; size is too small or we're not cleaning up properly */
86 LOGE("ERROR: max breakpoints exceeded\n");
87 assert(false);
88 }
89#else
90 assert(false);
91#endif
92}
93
94/*
95 * Remove an address from the list by setting the entry to NULL.
96 *
97 * This can be called from the JDWP thread (because the debugger has
98 * cancelled the breakpoint) or from an event thread (because it's a
99 * single-shot breakpoint, e.g. "run to line"). We only get here as
100 * the result of removing an entry from the event list, which is
101 * synchronized, so it should not be possible for two threads to be
102 * updating breakpoints at the same time.
103 */
104void dvmClearBreakAddr(Method* method, int instrOffset)
105{
106#ifdef WITH_DEBUGGER
107 const u2* addr = method->insns + instrOffset;
108 const u2** ptr = gDvm.debugBreakAddr;
109 int i;
110
111 LOGV("BKP: clear %p %s.%s (%s:%d)\n",
112 addr, method->clazz->descriptor, method->name,
113 dvmGetMethodSourceFile(method), dvmLineNumFromPC(method, instrOffset));
114
115 method->debugBreakpointCount--;
116 assert(method->debugBreakpointCount >= 0);
117 for (i = 0; i < MAX_BREAKPOINTS; i++, ptr++) {
118 if (*ptr == addr) {
119 *ptr = NULL;
120 break;
121 }
122 }
123 if (i == MAX_BREAKPOINTS) {
124 /* didn't find it */
125 LOGE("ERROR: breakpoint on %p not found\n", addr);
126 assert(false);
127 }
128#else
129 assert(false);
130#endif
131}
132
133/*
134 * Add a single step event. Currently this is a global item.
135 *
136 * We set up some initial values based on the thread's current state. This
137 * won't work well if the thread is running, so it's up to the caller to
138 * verify that it's suspended.
139 *
140 * This is only called from the JDWP thread.
141 */
142bool dvmAddSingleStep(Thread* thread, int size, int depth)
143{
144#ifdef WITH_DEBUGGER
145 StepControl* pCtrl = &gDvm.stepControl;
146
147 if (pCtrl->active && thread != pCtrl->thread) {
148 LOGW("WARNING: single-step active for %p; adding %p\n",
149 pCtrl->thread, thread);
150
151 /*
152 * Keep going, overwriting previous. This can happen if you
153 * suspend a thread in Object.wait, hit the single-step key, then
154 * switch to another thread and do the same thing again.
155 * The first thread's step is still pending.
156 *
157 * TODO: consider making single-step per-thread. Adds to the
158 * overhead, but could be useful in rare situations.
159 */
160 }
161
162 pCtrl->size = size;
163 pCtrl->depth = depth;
164 pCtrl->thread = thread;
165
166 /*
167 * We may be stepping into or over method calls, or running until we
168 * return from the current method. To make this work we need to track
169 * the current line, current method, and current stack depth. We need
170 * to be checking these after most instructions, notably those that
171 * call methods, return from methods, or are on a different line from the
172 * previous instruction.
173 *
174 * We have to start with a snapshot of the current state. If we're in
175 * an interpreted method, everything we need is in the current frame. If
176 * we're in a native method, possibly with some extra JNI frames pushed
177 * on by PushLocalFrame, we want to use the topmost native method.
178 */
179 const StackSaveArea* saveArea;
180 void* fp;
181 void* prevFp = NULL;
182
183 for (fp = thread->curFrame; fp != NULL; fp = saveArea->prevFrame) {
184 const Method* method;
185
186 saveArea = SAVEAREA_FROM_FP(fp);
187 method = saveArea->method;
188
189 if (!dvmIsBreakFrame(fp) && !dvmIsNativeMethod(method))
190 break;
191 prevFp = fp;
192 }
193 if (fp == NULL) {
194 LOGW("Unexpected: step req in native-only threadid=%d\n",
195 thread->threadId);
196 return false;
197 }
198 if (prevFp != NULL) {
199 /*
200 * First interpreted frame wasn't the one at the bottom. Break
201 * frames are only inserted when calling from native->interp, so we
202 * don't need to worry about one being here.
203 */
204 LOGV("##### init step while in native method\n");
205 fp = prevFp;
206 assert(!dvmIsBreakFrame(fp));
207 assert(dvmIsNativeMethod(SAVEAREA_FROM_FP(fp)->method));
208 saveArea = SAVEAREA_FROM_FP(fp);
209 }
210
211 /*
212 * Pull the goodies out. "xtra.currentPc" should be accurate since
213 * we update it on every instruction while the debugger is connected.
214 */
215 pCtrl->method = saveArea->method;
216 // Clear out any old address set
217 if (pCtrl->pAddressSet != NULL) {
218 // (discard const)
219 free((void *)pCtrl->pAddressSet);
220 pCtrl->pAddressSet = NULL;
221 }
222 if (dvmIsNativeMethod(pCtrl->method)) {
223 pCtrl->line = -1;
224 } else {
225 pCtrl->line = dvmLineNumFromPC(saveArea->method,
226 saveArea->xtra.currentPc - saveArea->method->insns);
227 pCtrl->pAddressSet
228 = dvmAddressSetForLine(saveArea->method, pCtrl->line);
229 }
230 pCtrl->frameDepth = dvmComputeVagueFrameDepth(thread, thread->curFrame);
231 pCtrl->active = true;
232
233 LOGV("##### step init: thread=%p meth=%p '%s' line=%d frameDepth=%d depth=%s size=%s\n",
234 pCtrl->thread, pCtrl->method, pCtrl->method->name,
235 pCtrl->line, pCtrl->frameDepth,
236 dvmJdwpStepDepthStr(pCtrl->depth),
237 dvmJdwpStepSizeStr(pCtrl->size));
238
239 return true;
240#else
241 assert(false);
242 return false;
243#endif
244}
245
246/*
247 * Disable a single step event.
248 */
249void dvmClearSingleStep(Thread* thread)
250{
251#ifdef WITH_DEBUGGER
252 UNUSED_PARAMETER(thread);
253
254 gDvm.stepControl.active = false;
255#else
256 assert(false);
257#endif
258}
259
260
261/*
262 * Recover the "this" pointer from the current interpreted method. "this"
263 * is always in "in0" for non-static methods.
264 *
265 * The "ins" start at (#of registers - #of ins). Note in0 != v0.
266 *
267 * This works because "dx" guarantees that it will work. It's probably
268 * fairly common to have a virtual method that doesn't use its "this"
269 * pointer, in which case we're potentially wasting a register. However,
270 * the debugger doesn't treat "this" as just another argument. For
271 * example, events (such as breakpoints) can be enabled for specific
272 * values of "this". There is also a separate StackFrame.ThisObject call
273 * in JDWP that is expected to work for any non-native non-static method.
274 *
275 * Because we need it when setting up debugger event filters, we want to
276 * be able to do this quickly.
277 */
278Object* dvmGetThisPtr(const Method* method, const u4* fp)
279{
280 if (dvmIsStaticMethod(method))
281 return NULL;
282 return (Object*)fp[method->registersSize - method->insSize];
283}
284
285
286#if defined(WITH_TRACKREF_CHECKS)
287/*
288 * Verify that all internally-tracked references have been released. If
289 * they haven't, print them and abort the VM.
290 *
291 * "debugTrackedRefStart" indicates how many refs were on the list when
292 * we were first invoked.
293 */
294void dvmInterpCheckTrackedRefs(Thread* self, const Method* method,
295 int debugTrackedRefStart)
296{
297 if (dvmReferenceTableEntries(&self->internalLocalRefTable)
298 != (size_t) debugTrackedRefStart)
299 {
300 char* desc;
301 Object** top;
302 int count;
303
304 count = dvmReferenceTableEntries(&self->internalLocalRefTable);
305
306 LOGE("TRACK: unreleased internal reference (prev=%d total=%d)\n",
307 debugTrackedRefStart, count);
308 desc = dexProtoCopyMethodDescriptor(&method->prototype);
309 LOGE(" current method is %s.%s %s\n", method->clazz->descriptor,
310 method->name, desc);
311 free(desc);
312 top = self->internalLocalRefTable.table + debugTrackedRefStart;
313 while (top < self->internalLocalRefTable.nextEntry) {
314 LOGE(" %p (%s)\n",
315 *top,
316 ((*top)->clazz != NULL) ? (*top)->clazz->descriptor : "");
317 top++;
318 }
319 dvmDumpThread(self, false);
320
321 dvmAbort();
322 }
323 //LOGI("TRACK OK\n");
324}
325#endif
326
327
328#ifdef LOG_INSTR
329/*
330 * Dump the v-registers. Sent to the ILOG log tag.
331 */
332void dvmDumpRegs(const Method* method, const u4* framePtr, bool inOnly)
333{
334 int i, localCount;
335
336 localCount = method->registersSize - method->insSize;
337
338 LOG(LOG_VERBOSE, LOG_TAG"i", "Registers (fp=%p):\n", framePtr);
339 for (i = method->registersSize-1; i >= 0; i--) {
340 if (i >= localCount) {
341 LOG(LOG_VERBOSE, LOG_TAG"i", " v%-2d in%-2d : 0x%08x\n",
342 i, i-localCount, framePtr[i]);
343 } else {
344 if (inOnly) {
345 LOG(LOG_VERBOSE, LOG_TAG"i", " [...]\n");
346 break;
347 }
348 const char* name = "";
349 int j;
350#if 0 // "locals" structure has changed -- need to rewrite this
351 DexFile* pDexFile = method->clazz->pDexFile;
352 const DexCode* pDexCode = dvmGetMethodCode(method);
353 int localsSize = dexGetLocalsSize(pDexFile, pDexCode);
354 const DexLocal* locals = dvmDexGetLocals(pDexFile, pDexCode);
355 for (j = 0; j < localsSize, j++) {
356 if (locals[j].registerNum == (u4) i) {
357 name = dvmDexStringStr(locals[j].pName);
358 break;
359 }
360 }
361#endif
362 LOG(LOG_VERBOSE, LOG_TAG"i", " v%-2d : 0x%08x %s\n",
363 i, framePtr[i], name);
364 }
365 }
366}
367#endif
368
369
370/*
371 * ===========================================================================
372 * Entry point and general support functions
373 * ===========================================================================
374 */
375
376/*
377 * Construct an s4 from two consecutive half-words of switch data.
378 * This needs to check endianness because the DEX optimizer only swaps
379 * half-words in instruction stream.
380 *
381 * "switchData" must be 32-bit aligned.
382 */
383#if __BYTE_ORDER == __LITTLE_ENDIAN
384static inline s4 s4FromSwitchData(const void* switchData) {
385 return *(s4*) switchData;
386}
387#else
388static inline s4 s4FromSwitchData(const void* switchData) {
389 u2* data = switchData;
390 return data[0] | (((s4) data[1]) << 16);
Jay Freeman (saurik)ffa5c292008-11-16 13:51:51 +0000391}
The Android Open Source Project2ad60cf2008-10-21 07:00:00 -0700392#endif
393
394/*
395 * Find the matching case. Returns the offset to the handler instructions.
396 *
397 * Returns 3 if we don't find a match (it's the size of the packed-switch
398 * instruction).
399 */
400s4 dvmInterpHandlePackedSwitch(const u2* switchData, s4 testVal)
401{
402 const int kInstrLen = 3;
403 u2 size;
404 s4 firstKey;
405 const s4* entries;
406
407 /*
408 * Packed switch data format:
409 * ushort ident = 0x0100 magic value
410 * ushort size number of entries in the table
411 * int first_key first (and lowest) switch case value
412 * int targets[size] branch targets, relative to switch opcode
413 *
414 * Total size is (4+size*2) 16-bit code units.
415 */
416 if (*switchData++ != kPackedSwitchSignature) {
417 /* should have been caught by verifier */
418 dvmThrowException("Ljava/lang/InternalError;",
419 "bad packed switch magic");
420 return kInstrLen;
421 }
422
423 size = *switchData++;
424 assert(size > 0);
425
426 firstKey = *switchData++;
427 firstKey |= (*switchData++) << 16;
428
429 if (testVal < firstKey || testVal >= firstKey + size) {
430 LOGVV("Value %d not found in switch (%d-%d)\n",
431 testVal, firstKey, firstKey+size-1);
432 return kInstrLen;
433 }
434
435 /* The entries are guaranteed to be aligned on a 32-bit boundary;
436 * we can treat them as a native int array.
437 */
438 entries = (const s4*) switchData;
439 assert(((u4)entries & 0x3) == 0);
440
441 assert(testVal - firstKey >= 0 && testVal - firstKey < size);
442 LOGVV("Value %d found in slot %d (goto 0x%02x)\n",
443 testVal, testVal - firstKey,
444 s4FromSwitchData(&entries[testVal - firstKey]));
445 return s4FromSwitchData(&entries[testVal - firstKey]);
446}
447
448/*
449 * Find the matching case. Returns the offset to the handler instructions.
450 *
451 * Returns 3 if we don't find a match (it's the size of the sparse-switch
452 * instruction).
453 */
454s4 dvmInterpHandleSparseSwitch(const u2* switchData, s4 testVal)
455{
456 const int kInstrLen = 3;
457 u2 ident, size;
458 const s4* keys;
459 const s4* entries;
460 int i;
461
462 /*
463 * Sparse switch data format:
464 * ushort ident = 0x0200 magic value
465 * ushort size number of entries in the table; > 0
466 * int keys[size] keys, sorted low-to-high; 32-bit aligned
467 * int targets[size] branch targets, relative to switch opcode
468 *
469 * Total size is (2+size*4) 16-bit code units.
470 */
471
472 if (*switchData++ != kSparseSwitchSignature) {
473 /* should have been caught by verifier */
474 dvmThrowException("Ljava/lang/InternalError;",
475 "bad sparse switch magic");
476 return kInstrLen;
477 }
478
479 size = *switchData++;
480 assert(size > 0);
481
482 /* The keys are guaranteed to be aligned on a 32-bit boundary;
483 * we can treat them as a native int array.
484 */
485 keys = (const s4*) switchData;
486 assert(((u4)keys & 0x3) == 0);
487
488 /* The entries are guaranteed to be aligned on a 32-bit boundary;
489 * we can treat them as a native int array.
490 */
491 entries = keys + size;
492 assert(((u4)entries & 0x3) == 0);
493
494 /*
495 * Run through the list of keys, which are guaranteed to
496 * be sorted low-to-high.
497 *
498 * Most tables have 3-4 entries. Few have more than 10. A binary
499 * search here is probably not useful.
500 */
501 for (i = 0; i < size; i++) {
502 s4 k = s4FromSwitchData(&keys[i]);
503 if (k == testVal) {
504 LOGVV("Value %d found in entry %d (goto 0x%02x)\n",
505 testVal, i, s4FromSwitchData(&entries[i]));
506 return s4FromSwitchData(&entries[i]);
507 } else if (k > testVal) {
508 break;
509 }
510 }
511
512 LOGVV("Value %d not found in switch\n", testVal);
513 return kInstrLen;
514}
515
516/*
517 * Fill the array with predefined constant values.
518 *
519 * Returns true if job is completed, otherwise false to indicate that
520 * an exception has been thrown.
521 */
522bool dvmInterpHandleFillArrayData(ArrayObject* arrayObj,
523 const u2* arrayData)
524{
525 u2 width;
526 u4 size;
527
528 if (!checkForNull((Object*) arrayObj)) {
529 return false;
530 }
531 /*
532 * Array data table format:
533 * ushort ident = 0x0300 magic value
534 * ushort width width of each element in the table
535 * uint size number of elements in the table
536 * ubyte data[size*width] table of data values (may contain a single-byte
537 * padding at the end)
538 *
539 * Total size is 4+(width * size + 1)/2 16-bit code units.
540 */
541 if (arrayData[0] != kArrayDataSignature) {
542 dvmThrowException("Ljava/lang/InternalError;", "bad array data magic");
543 return false;
544 }
545
546 width = arrayData[1];
547 size = arrayData[2] | (((u4)arrayData[3]) << 16);
548
549 if (size != arrayObj->length) {
550 dvmThrowException("Ljava/lang/ArrayIndexOutOfBoundsException;", NULL);
551 return false;
552 }
553 memcpy(arrayObj->contents, &arrayData[4], size*width);
554 return true;
555}
556
557/*
558 * Find the concrete method that corresponds to "methodIdx". The code in
559 * "method" is executing invoke-method with "thisClass" as its first argument.
560 *
561 * Returns NULL with an exception raised on failure.
562 */
563Method* dvmInterpFindInterfaceMethod(ClassObject* thisClass, u4 methodIdx,
564 const Method* method, DvmDex* methodClassDex)
565{
566 Method* absMethod;
567 Method* methodToCall;
568 int i, vtableIndex;
569
570 /*
571 * Resolve the method. This gives us the abstract method from the
572 * interface class declaration.
573 */
574 absMethod = dvmDexGetResolvedMethod(methodClassDex, methodIdx);
575 if (absMethod == NULL) {
576 absMethod = dvmResolveInterfaceMethod(method->clazz, methodIdx);
577 if (absMethod == NULL) {
578 LOGV("+ unknown method\n");
579 return NULL;
580 }
581 }
582
583 /* make sure absMethod->methodIndex means what we think it means */
584 assert(dvmIsAbstractMethod(absMethod));
585
586 /*
587 * Run through the "this" object's iftable. Find the entry for
588 * absMethod's class, then use absMethod->methodIndex to find
589 * the method's entry. The value there is the offset into our
590 * vtable of the actual method to execute.
591 *
592 * The verifier does not guarantee that objects stored into
593 * interface references actually implement the interface, so this
594 * check cannot be eliminated.
595 */
596 for (i = 0; i < thisClass->iftableCount; i++) {
597 if (thisClass->iftable[i].clazz == absMethod->clazz)
598 break;
599 }
600 if (i == thisClass->iftableCount) {
601 /* impossible in verified DEX, need to check for it in unverified */
602 dvmThrowException("Ljava/lang/IncompatibleClassChangeError;",
603 "interface not implemented");
604 return NULL;
605 }
606
607 assert(absMethod->methodIndex <
608 thisClass->iftable[i].clazz->virtualMethodCount);
609
610 vtableIndex =
611 thisClass->iftable[i].methodIndexArray[absMethod->methodIndex];
612 assert(vtableIndex >= 0 && vtableIndex < thisClass->vtableCount);
613 methodToCall = thisClass->vtable[vtableIndex];
614
615#if 0
616 /* this can happen when there's a stale class file */
617 if (dvmIsAbstractMethod(methodToCall)) {
618 dvmThrowException("Ljava/lang/AbstractMethodError;",
619 "interface method not implemented");
620 return NULL;
621 }
622#else
623 assert(!dvmIsAbstractMethod(methodToCall) ||
624 methodToCall->nativeFunc != NULL);
625#endif
626
627 LOGVV("+++ interface=%s.%s concrete=%s.%s\n",
628 absMethod->clazz->descriptor, absMethod->name,
629 methodToCall->clazz->descriptor, methodToCall->name);
630 assert(methodToCall != NULL);
631
632 return methodToCall;
633}
634
635
636/*
637 * Main interpreter loop entry point. Select "standard" or "debug"
638 * interpreter and switch between them as required.
639 *
640 * This begins executing code at the start of "method". On exit, "pResult"
641 * holds the return value of the method (or, if "method" returns NULL, it
642 * holds an undefined value).
643 *
644 * The interpreted stack frame, which holds the method arguments, has
645 * already been set up.
646 */
647void dvmInterpret(Thread* self, const Method* method, JValue* pResult)
648{
649 InterpState interpState;
650 bool change;
651
652#if defined(WITH_TRACKREF_CHECKS)
653 interpState.debugTrackedRefStart =
654 dvmReferenceTableEntries(&self->internalLocalRefTable);
655#endif
656#if defined(WITH_PROFILER) || defined(WITH_DEBUGGER)
657 interpState.debugIsMethodEntry = true;
658#endif
659
660 /*
661 * Initialize working state.
662 *
663 * No need to initialize "retval".
664 */
665 interpState.method = method;
666 interpState.fp = (u4*) self->curFrame;
667 interpState.pc = method->insns;
668 interpState.entryPoint = kInterpEntryInstr;
669
670 if (dvmDebuggerOrProfilerActive())
671 interpState.nextMode = INTERP_DBG;
672 else
673 interpState.nextMode = INTERP_STD;
674
675 assert(!dvmIsNativeMethod(method));
676
677 /*
678 * Make sure the class is ready to go. Shouldn't be possible to get
679 * here otherwise.
680 */
681 if (method->clazz->status < CLASS_INITIALIZING ||
682 method->clazz->status == CLASS_ERROR)
683 {
684 LOGE("ERROR: tried to execute code in unprepared class '%s' (%d)\n",
685 method->clazz->descriptor, method->clazz->status);
686 dvmDumpThread(self, false);
687 dvmAbort();
688 }
689
690 typedef bool (*Interpreter)(Thread*, InterpState*);
691 Interpreter stdInterp;
692 if (gDvm.executionMode == kExecutionModeInterpFast)
693 stdInterp = dvmMterpStd;
694 else
695 stdInterp = dvmInterpretStd;
696
697 change = true;
698 while (change) {
699 switch (interpState.nextMode) {
700 case INTERP_STD:
701 LOGVV("threadid=%d: interp STD\n", self->threadId);
702 change = (*stdInterp)(self, &interpState);
703 break;
704#if defined(WITH_PROFILER) || defined(WITH_DEBUGGER)
705 case INTERP_DBG:
706 LOGVV("threadid=%d: interp DBG\n", self->threadId);
707 change = dvmInterpretDbg(self, &interpState);
708 break;
709#endif
710 default:
711 dvmAbort();
712 }
713 }
714
715 *pResult = interpState.retval;
716}