Home | History | Annotate | Download | only in interp
      1 /*
      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 /*
     18  * Stacks and their uses (e.g. native --> interpreted method calls).
     19  *
     20  * See the majestic ASCII art in Stack.h.
     21  */
     22 #include "Dalvik.h"
     23 #include "jni.h"
     24 
     25 #include <stdlib.h>
     26 #include <stdarg.h>
     27 
     28 #ifdef HAVE_ANDROID_OS
     29 #include <corkscrew/backtrace.h>
     30 #endif
     31 
     32 /*
     33  * Initialize the interpreter stack in a new thread.
     34  *
     35  * Currently this doesn't do much, since we don't need to zero out the
     36  * stack (and we really don't want to if it was created with mmap).
     37  */
     38 bool dvmInitInterpStack(Thread* thread, int stackSize)
     39 {
     40     assert(thread->interpStackStart != NULL);
     41 
     42     assert(thread->interpSave.curFrame == NULL);
     43 
     44     return true;
     45 }
     46 
     47 /*
     48  * We're calling an interpreted method from an internal VM function or
     49  * via reflection.
     50  *
     51  * Push a frame for an interpreted method onto the stack.  This is only
     52  * used when calling into interpreted code from native code.  (The
     53  * interpreter does its own stack frame manipulation for interp-->interp
     54  * calls.)
     55  *
     56  * The size we need to reserve is the sum of parameters, local variables,
     57  * saved goodies, and outbound parameters.
     58  *
     59  * We start by inserting a "break" frame, which ensures that the interpreter
     60  * hands control back to us after the function we call returns or an
     61  * uncaught exception is thrown.
     62  */
     63 static bool dvmPushInterpFrame(Thread* self, const Method* method)
     64 {
     65     StackSaveArea* saveBlock;
     66     StackSaveArea* breakSaveBlock;
     67     int stackReq;
     68     u1* stackPtr;
     69 
     70     assert(!dvmIsNativeMethod(method));
     71     assert(!dvmIsAbstractMethod(method));
     72 
     73     stackReq = method->registersSize * 4        // params + locals
     74                 + sizeof(StackSaveArea) * 2     // break frame + regular frame
     75                 + method->outsSize * 4;         // args to other methods
     76 
     77     if (self->interpSave.curFrame != NULL)
     78         stackPtr = (u1*) SAVEAREA_FROM_FP(self->interpSave.curFrame);
     79     else
     80         stackPtr = self->interpStackStart;
     81 
     82     if (stackPtr - stackReq < self->interpStackEnd) {
     83         /* not enough space */
     84         ALOGW("Stack overflow on call to interp "
     85              "(req=%d top=%p cur=%p size=%d %s.%s)",
     86             stackReq, self->interpStackStart, self->interpSave.curFrame,
     87             self->interpStackSize, method->clazz->descriptor, method->name);
     88         dvmHandleStackOverflow(self, method);
     89         assert(dvmCheckException(self));
     90         return false;
     91     }
     92 
     93     /*
     94      * Shift the stack pointer down, leaving space for the function's
     95      * args/registers and save area.
     96      */
     97     stackPtr -= sizeof(StackSaveArea);
     98     breakSaveBlock = (StackSaveArea*)stackPtr;
     99     stackPtr -= method->registersSize * 4 + sizeof(StackSaveArea);
    100     saveBlock = (StackSaveArea*) stackPtr;
    101 
    102 #if !defined(NDEBUG) && !defined(PAD_SAVE_AREA)
    103     /* debug -- memset the new stack, unless we want valgrind's help */
    104     memset(stackPtr - (method->outsSize*4), 0xaf, stackReq);
    105 #endif
    106 #ifdef EASY_GDB
    107     breakSaveBlock->prevSave =
    108        (StackSaveArea*)FP_FROM_SAVEAREA(self->interpSave.curFrame);
    109     saveBlock->prevSave = breakSaveBlock;
    110 #endif
    111 
    112     breakSaveBlock->prevFrame = self->interpSave.curFrame;
    113     breakSaveBlock->savedPc = NULL;             // not required
    114     breakSaveBlock->xtra.localRefCookie = 0;    // not required
    115     breakSaveBlock->method = NULL;
    116     saveBlock->prevFrame = FP_FROM_SAVEAREA(breakSaveBlock);
    117     saveBlock->savedPc = NULL;                  // not required
    118     saveBlock->xtra.currentPc = NULL;           // not required?
    119     saveBlock->method = method;
    120 
    121     LOGVV("PUSH frame: old=%p new=%p (size=%d)",
    122         self->interpSave.curFrame, FP_FROM_SAVEAREA(saveBlock),
    123         (u1*)self->interpSave.curFrame - (u1*)FP_FROM_SAVEAREA(saveBlock));
    124 
    125     self->interpSave.curFrame = FP_FROM_SAVEAREA(saveBlock);
    126 
    127     return true;
    128 }
    129 
    130 /*
    131  * We're calling a JNI native method from an internal VM fuction or
    132  * via reflection.  This is also used to create the "fake" native-method
    133  * frames at the top of the interpreted stack.
    134  *
    135  * This actually pushes two frames; the first is a "break" frame.
    136  *
    137  * The top frame has additional space for JNI local reference tracking.
    138  */
    139 bool dvmPushJNIFrame(Thread* self, const Method* method)
    140 {
    141     StackSaveArea* saveBlock;
    142     StackSaveArea* breakSaveBlock;
    143     int stackReq;
    144     u1* stackPtr;
    145 
    146     assert(dvmIsNativeMethod(method));
    147 
    148     stackReq = method->registersSize * 4        // params only
    149                 + sizeof(StackSaveArea) * 2;    // break frame + regular frame
    150 
    151     if (self->interpSave.curFrame != NULL)
    152         stackPtr = (u1*) SAVEAREA_FROM_FP(self->interpSave.curFrame);
    153     else
    154         stackPtr = self->interpStackStart;
    155 
    156     if (stackPtr - stackReq < self->interpStackEnd) {
    157         /* not enough space */
    158         ALOGW("Stack overflow on call to native "
    159              "(req=%d top=%p cur=%p size=%d '%s')",
    160             stackReq, self->interpStackStart, self->interpSave.curFrame,
    161             self->interpStackSize, method->name);
    162         dvmHandleStackOverflow(self, method);
    163         assert(dvmCheckException(self));
    164         return false;
    165     }
    166 
    167     /*
    168      * Shift the stack pointer down, leaving space for just the stack save
    169      * area for the break frame, then shift down farther for the full frame.
    170      * We leave space for the method args, which are copied in later.
    171      */
    172     stackPtr -= sizeof(StackSaveArea);
    173     breakSaveBlock = (StackSaveArea*)stackPtr;
    174     stackPtr -= method->registersSize * 4 + sizeof(StackSaveArea);
    175     saveBlock = (StackSaveArea*) stackPtr;
    176 
    177 #if !defined(NDEBUG) && !defined(PAD_SAVE_AREA)
    178     /* debug -- memset the new stack */
    179     memset(stackPtr, 0xaf, stackReq);
    180 #endif
    181 #ifdef EASY_GDB
    182     if (self->interpSave.curFrame == NULL)
    183         breakSaveBlock->prevSave = NULL;
    184     else {
    185         void* fp = FP_FROM_SAVEAREA(self->interpSave.curFrame);
    186         breakSaveBlock->prevSave = (StackSaveArea*)fp;
    187     }
    188     saveBlock->prevSave = breakSaveBlock;
    189 #endif
    190 
    191     breakSaveBlock->prevFrame = self->interpSave.curFrame;
    192     breakSaveBlock->savedPc = NULL;             // not required
    193     breakSaveBlock->xtra.localRefCookie = 0;    // not required
    194     breakSaveBlock->method = NULL;
    195     saveBlock->prevFrame = FP_FROM_SAVEAREA(breakSaveBlock);
    196     saveBlock->savedPc = NULL;                  // not required
    197     saveBlock->xtra.localRefCookie = self->jniLocalRefTable.segmentState.all;
    198     saveBlock->method = method;
    199 
    200     LOGVV("PUSH JNI frame: old=%p new=%p (size=%d)",
    201         self->interpSave.curFrame, FP_FROM_SAVEAREA(saveBlock),
    202         (u1*)self->interpSave.curFrame - (u1*)FP_FROM_SAVEAREA(saveBlock));
    203 
    204     self->interpSave.curFrame = FP_FROM_SAVEAREA(saveBlock);
    205 
    206     return true;
    207 }
    208 
    209 /*
    210  * This is used by the JNI PushLocalFrame call.  We push a new frame onto
    211  * the stack that has no ins, outs, or locals, and no break frame above it.
    212  * It's strictly used for tracking JNI local refs, and will be popped off
    213  * by dvmPopFrame if it's not removed explicitly.
    214  */
    215 bool dvmPushLocalFrame(Thread* self, const Method* method)
    216 {
    217     StackSaveArea* saveBlock;
    218     int stackReq;
    219     u1* stackPtr;
    220 
    221     assert(dvmIsNativeMethod(method));
    222 
    223     stackReq = sizeof(StackSaveArea);       // regular frame
    224 
    225     assert(self->interpSave.curFrame != NULL);
    226     stackPtr = (u1*) SAVEAREA_FROM_FP(self->interpSave.curFrame);
    227 
    228     if (stackPtr - stackReq < self->interpStackEnd) {
    229         /* not enough space; let JNI throw the exception */
    230         ALOGW("Stack overflow on PushLocal "
    231              "(req=%d top=%p cur=%p size=%d '%s')",
    232             stackReq, self->interpStackStart, self->interpSave.curFrame,
    233             self->interpStackSize, method->name);
    234         dvmHandleStackOverflow(self, method);
    235         assert(dvmCheckException(self));
    236         return false;
    237     }
    238 
    239     /*
    240      * Shift the stack pointer down, leaving space for just the stack save
    241      * area for the break frame, then shift down farther for the full frame.
    242      */
    243     stackPtr -= sizeof(StackSaveArea);
    244     saveBlock = (StackSaveArea*) stackPtr;
    245 
    246 #if !defined(NDEBUG) && !defined(PAD_SAVE_AREA)
    247     /* debug -- memset the new stack */
    248     memset(stackPtr, 0xaf, stackReq);
    249 #endif
    250 #ifdef EASY_GDB
    251     saveBlock->prevSave =
    252         (StackSaveArea*)FP_FROM_SAVEAREA(self->interpSave.curFrame);
    253 #endif
    254 
    255     saveBlock->prevFrame = self->interpSave.curFrame;
    256     saveBlock->savedPc = NULL;                  // not required
    257     saveBlock->xtra.localRefCookie = self->jniLocalRefTable.segmentState.all;
    258     saveBlock->method = method;
    259 
    260     LOGVV("PUSH JNI local frame: old=%p new=%p (size=%d)",
    261         self->interpSave.curFrame, FP_FROM_SAVEAREA(saveBlock),
    262         (u1*)self->interpSave.curFrame - (u1*)FP_FROM_SAVEAREA(saveBlock));
    263 
    264     self->interpSave.curFrame = FP_FROM_SAVEAREA(saveBlock);
    265 
    266     return true;
    267 }
    268 
    269 /*
    270  * Pop one frame pushed on by JNI PushLocalFrame.
    271  *
    272  * If we've gone too far, the previous frame is either a break frame or
    273  * an interpreted frame.  Either way, the method pointer won't match.
    274  */
    275 bool dvmPopLocalFrame(Thread* self)
    276 {
    277     StackSaveArea* saveBlock = SAVEAREA_FROM_FP(self->interpSave.curFrame);
    278 
    279     assert(!dvmIsBreakFrame((u4*)self->interpSave.curFrame));
    280     if (saveBlock->method != SAVEAREA_FROM_FP(saveBlock->prevFrame)->method) {
    281         /*
    282          * The previous frame doesn't have the same method pointer -- we've
    283          * been asked to pop too much.
    284          */
    285         assert(dvmIsBreakFrame((u4*)saveBlock->prevFrame) ||
    286                !dvmIsNativeMethod(
    287                        SAVEAREA_FROM_FP(saveBlock->prevFrame)->method));
    288         return false;
    289     }
    290 
    291     LOGVV("POP JNI local frame: removing %s, now %s",
    292         saveBlock->method->name,
    293         SAVEAREA_FROM_FP(saveBlock->prevFrame)->method->name);
    294     dvmPopJniLocals(self, saveBlock);
    295     self->interpSave.curFrame = saveBlock->prevFrame;
    296 
    297     return true;
    298 }
    299 
    300 /*
    301  * Pop a frame we added.  There should be one method frame and one break
    302  * frame.
    303  *
    304  * If JNI Push/PopLocalFrame calls were mismatched, we might end up
    305  * popping multiple method frames before we find the break.
    306  *
    307  * Returns "false" if there was no frame to pop.
    308  */
    309 static bool dvmPopFrame(Thread* self)
    310 {
    311     StackSaveArea* saveBlock;
    312 
    313     if (self->interpSave.curFrame == NULL)
    314         return false;
    315 
    316     saveBlock = SAVEAREA_FROM_FP(self->interpSave.curFrame);
    317     assert(!dvmIsBreakFrame((u4*)self->interpSave.curFrame));
    318 
    319     /*
    320      * Remove everything up to the break frame.  If this was a call into
    321      * native code, pop the JNI local references table.
    322      */
    323     while (saveBlock->prevFrame != NULL && saveBlock->method != NULL) {
    324         /* probably a native->native JNI call */
    325 
    326         if (dvmIsNativeMethod(saveBlock->method)) {
    327             LOGVV("Popping JNI stack frame for %s.%s%s",
    328                 saveBlock->method->clazz->descriptor,
    329                 saveBlock->method->name,
    330                 (SAVEAREA_FROM_FP(saveBlock->prevFrame)->method == NULL) ?
    331                 "" : " (JNI local)");
    332             dvmPopJniLocals(self, saveBlock);
    333         }
    334 
    335         saveBlock = SAVEAREA_FROM_FP(saveBlock->prevFrame);
    336     }
    337     if (saveBlock->method != NULL) {
    338         ALOGE("PopFrame missed the break");
    339         assert(false);
    340         dvmAbort();     // stack trashed -- nowhere to go in this thread
    341     }
    342 
    343     LOGVV("POP frame: cur=%p new=%p",
    344         self->interpSave.curFrame, saveBlock->prevFrame);
    345 
    346     self->interpSave.curFrame = saveBlock->prevFrame;
    347     return true;
    348 }
    349 
    350 /*
    351  * Common code for dvmCallMethodV/A and dvmInvokeMethod.
    352  *
    353  * Pushes a call frame on, advancing self->interpSave.curFrame.
    354  */
    355 static ClassObject* callPrep(Thread* self, const Method* method, Object* obj,
    356     bool checkAccess)
    357 {
    358     ClassObject* clazz;
    359 
    360 #ifndef NDEBUG
    361     if (self->status != THREAD_RUNNING) {
    362         ALOGW("threadid=%d: status=%d on call to %s.%s -",
    363             self->threadId, self->status,
    364             method->clazz->descriptor, method->name);
    365     }
    366 #endif
    367 
    368     assert(self != NULL);
    369     assert(method != NULL);
    370 
    371     if (obj != NULL)
    372         clazz = obj->clazz;
    373     else
    374         clazz = method->clazz;
    375 
    376     IF_LOGVV() {
    377         char* desc = dexProtoCopyMethodDescriptor(&method->prototype);
    378         LOGVV("thread=%d native code calling %s.%s %s", self->threadId,
    379             clazz->descriptor, method->name, desc);
    380         free(desc);
    381     }
    382 
    383     if (checkAccess) {
    384         /* needed for java.lang.reflect.Method.invoke */
    385         if (!dvmCheckMethodAccess(dvmGetCaller2Class(self->interpSave.curFrame),
    386                 method))
    387         {
    388             /* note this throws IAException, not IAError */
    389             dvmThrowIllegalAccessException("access to method denied");
    390             return NULL;
    391         }
    392     }
    393 
    394     /*
    395      * Push a call frame on.  If there isn't enough room for ins, locals,
    396      * outs, and the saved state, it will throw an exception.
    397      *
    398      * This updates self->interpSave.curFrame.
    399      */
    400     if (dvmIsNativeMethod(method)) {
    401         /* native code calling native code the hard way */
    402         if (!dvmPushJNIFrame(self, method)) {
    403             assert(dvmCheckException(self));
    404             return NULL;
    405         }
    406     } else {
    407         /* native code calling interpreted code */
    408         if (!dvmPushInterpFrame(self, method)) {
    409             assert(dvmCheckException(self));
    410             return NULL;
    411         }
    412     }
    413 
    414     return clazz;
    415 }
    416 
    417 /*
    418  * Issue a method call.
    419  *
    420  * Pass in NULL for "obj" on calls to static methods.
    421  *
    422  * (Note this can't be inlined because it takes a variable number of args.)
    423  */
    424 void dvmCallMethod(Thread* self, const Method* method, Object* obj,
    425     JValue* pResult, ...)
    426 {
    427     va_list args;
    428     va_start(args, pResult);
    429     dvmCallMethodV(self, method, obj, false, pResult, args);
    430     va_end(args);
    431 }
    432 
    433 /*
    434  * Issue a method call with a variable number of arguments.  We process
    435  * the contents of "args" by scanning the method signature.
    436  *
    437  * Pass in NULL for "obj" on calls to static methods.
    438  *
    439  * We don't need to take the class as an argument because, in Dalvik,
    440  * we don't need to worry about static synchronized methods.
    441  */
    442 void dvmCallMethodV(Thread* self, const Method* method, Object* obj,
    443     bool fromJni, JValue* pResult, va_list args)
    444 {
    445     const char* desc = &(method->shorty[1]); // [0] is the return type.
    446     int verifyCount = 0;
    447     ClassObject* clazz;
    448     u4* ins;
    449 
    450     clazz = callPrep(self, method, obj, false);
    451     if (clazz == NULL)
    452         return;
    453 
    454     /* "ins" for new frame start at frame pointer plus locals */
    455     ins = ((u4*)self->interpSave.curFrame) +
    456            (method->registersSize - method->insSize);
    457 
    458     //ALOGD("  FP is %p, INs live at >= %p", self->interpSave.curFrame, ins);
    459 
    460     /* put "this" pointer into in0 if appropriate */
    461     if (!dvmIsStaticMethod(method)) {
    462 #ifdef WITH_EXTRA_OBJECT_VALIDATION
    463         assert(obj != NULL && dvmIsHeapAddress(obj));
    464 #endif
    465         *ins++ = (u4) obj;
    466         verifyCount++;
    467     }
    468 
    469     while (*desc != '\0') {
    470         switch (*(desc++)) {
    471             case 'D': case 'J': {
    472                 u8 val = va_arg(args, u8);
    473                 memcpy(ins, &val, 8);       // EABI prevents direct store
    474                 ins += 2;
    475                 verifyCount += 2;
    476                 break;
    477             }
    478             case 'F': {
    479                 /* floats were normalized to doubles; convert back */
    480                 float f = (float) va_arg(args, double);
    481                 *ins++ = dvmFloatToU4(f);
    482                 verifyCount++;
    483                 break;
    484             }
    485             case 'L': {     /* 'shorty' descr uses L for all refs, incl array */
    486                 void* arg = va_arg(args, void*);
    487                 assert(obj == NULL || dvmIsHeapAddress(obj));
    488                 jobject argObj = reinterpret_cast<jobject>(arg);
    489                 if (fromJni)
    490                     *ins++ = (u4) dvmDecodeIndirectRef(self, argObj);
    491                 else
    492                     *ins++ = (u4) argObj;
    493                 verifyCount++;
    494                 break;
    495             }
    496             default: {
    497                 /* Z B C S I -- all passed as 32-bit integers */
    498                 *ins++ = va_arg(args, u4);
    499                 verifyCount++;
    500                 break;
    501             }
    502         }
    503     }
    504 
    505 #ifndef NDEBUG
    506     if (verifyCount != method->insSize) {
    507         ALOGE("Got vfycount=%d insSize=%d for %s.%s", verifyCount,
    508             method->insSize, clazz->descriptor, method->name);
    509         assert(false);
    510         goto bail;
    511     }
    512 #endif
    513 
    514     //dvmDumpThreadStack(dvmThreadSelf());
    515 
    516     if (dvmIsNativeMethod(method)) {
    517         TRACE_METHOD_ENTER(self, method);
    518         /*
    519          * Because we leave no space for local variables, "curFrame" points
    520          * directly at the method arguments.
    521          */
    522         (*method->nativeFunc)((u4*)self->interpSave.curFrame, pResult,
    523                               method, self);
    524         TRACE_METHOD_EXIT(self, method);
    525     } else {
    526         dvmInterpret(self, method, pResult);
    527     }
    528 
    529 #ifndef NDEBUG
    530 bail:
    531 #endif
    532     dvmPopFrame(self);
    533 }
    534 
    535 /*
    536  * Issue a method call with arguments provided in an array.  We process
    537  * the contents of "args" by scanning the method signature.
    538  *
    539  * The values were likely placed into an uninitialized jvalue array using
    540  * the field specifiers, which means that sub-32-bit fields (e.g. short,
    541  * boolean) may not have 32 or 64 bits of valid data.  This is different
    542  * from the varargs invocation where the C compiler does a widening
    543  * conversion when calling a function.  As a result, we have to be a
    544  * little more precise when pulling stuff out.
    545  *
    546  * "args" may be NULL if the method has no arguments.
    547  */
    548 void dvmCallMethodA(Thread* self, const Method* method, Object* obj,
    549     bool fromJni, JValue* pResult, const jvalue* args)
    550 {
    551     const char* desc = &(method->shorty[1]); // [0] is the return type.
    552     int verifyCount = 0;
    553     ClassObject* clazz;
    554     u4* ins;
    555 
    556     clazz = callPrep(self, method, obj, false);
    557     if (clazz == NULL)
    558         return;
    559 
    560     /* "ins" for new frame start at frame pointer plus locals */
    561     ins = ((u4*)self->interpSave.curFrame) +
    562         (method->registersSize - method->insSize);
    563 
    564     /* put "this" pointer into in0 if appropriate */
    565     if (!dvmIsStaticMethod(method)) {
    566         assert(obj != NULL);
    567         *ins++ = (u4) obj;              /* obj is a "real" ref */
    568         verifyCount++;
    569     }
    570 
    571     while (*desc != '\0') {
    572         switch (*desc++) {
    573         case 'D':                       /* 64-bit quantity; have to use */
    574         case 'J':                       /*  memcpy() in case of mis-alignment */
    575             memcpy(ins, &args->j, 8);
    576             ins += 2;
    577             verifyCount++;              /* this needs an extra push */
    578             break;
    579         case 'L':                       /* includes array refs */
    580             if (fromJni)
    581                 *ins++ = (u4) dvmDecodeIndirectRef(self, args->l);
    582             else
    583                 *ins++ = (u4) args->l;
    584             break;
    585         case 'F':
    586         case 'I':
    587             *ins++ = args->i;           /* full 32 bits */
    588             break;
    589         case 'S':
    590             *ins++ = args->s;           /* 16 bits, sign-extended */
    591             break;
    592         case 'C':
    593             *ins++ = args->c;           /* 16 bits, unsigned */
    594             break;
    595         case 'B':
    596             *ins++ = args->b;           /* 8 bits, sign-extended */
    597             break;
    598         case 'Z':
    599             *ins++ = args->z;           /* 8 bits, zero or non-zero */
    600             break;
    601         default:
    602             ALOGE("Invalid char %c in short signature of %s.%s",
    603                 *(desc-1), clazz->descriptor, method->name);
    604             assert(false);
    605             goto bail;
    606         }
    607 
    608         verifyCount++;
    609         args++;
    610     }
    611 
    612 #ifndef NDEBUG
    613     if (verifyCount != method->insSize) {
    614         ALOGE("Got vfycount=%d insSize=%d for %s.%s", verifyCount,
    615             method->insSize, clazz->descriptor, method->name);
    616         assert(false);
    617         goto bail;
    618     }
    619 #endif
    620 
    621     if (dvmIsNativeMethod(method)) {
    622         TRACE_METHOD_ENTER(self, method);
    623         /*
    624          * Because we leave no space for local variables, "curFrame" points
    625          * directly at the method arguments.
    626          */
    627         (*method->nativeFunc)((u4*)self->interpSave.curFrame, pResult,
    628                               method, self);
    629         TRACE_METHOD_EXIT(self, method);
    630     } else {
    631         dvmInterpret(self, method, pResult);
    632     }
    633 
    634 bail:
    635     dvmPopFrame(self);
    636 }
    637 
    638 static void throwArgumentTypeMismatch(int argIndex, ClassObject* expected, DataObject* arg) {
    639     std::string expectedClassName(dvmHumanReadableDescriptor(expected->descriptor));
    640     std::string actualClassName = dvmHumanReadableType(arg);
    641     dvmThrowExceptionFmt(gDvm.exIllegalArgumentException, "argument %d should have type %s, got %s",
    642             argIndex + 1, expectedClassName.c_str(), actualClassName.c_str());
    643 }
    644 
    645 /*
    646  * Invoke a method, using the specified arguments and return type, through
    647  * one of the reflection interfaces.  Could be a virtual or direct method
    648  * (including constructors).  Used for reflection.
    649  *
    650  * Deals with boxing/unboxing primitives and performs widening conversions.
    651  *
    652  * "invokeObj" will be null for a static method.
    653  *
    654  * If the invocation returns with an exception raised, we have to wrap it.
    655  */
    656 Object* dvmInvokeMethod(Object* obj, const Method* method,
    657     ArrayObject* argList, ArrayObject* params, ClassObject* returnType,
    658     bool noAccessCheck)
    659 {
    660     ClassObject* clazz;
    661     Object* retObj = NULL;
    662     Thread* self = dvmThreadSelf();
    663     s4* ins;
    664     int verifyCount, argListLength;
    665     JValue retval;
    666     bool needPop = false;
    667 
    668     /* verify arg count */
    669     if (argList != NULL)
    670         argListLength = argList->length;
    671     else
    672         argListLength = 0;
    673     if (argListLength != (int) params->length) {
    674         dvmThrowExceptionFmt(gDvm.exIllegalArgumentException,
    675             "wrong number of arguments; expected %d, got %d",
    676             params->length, argListLength);
    677         return NULL;
    678     }
    679 
    680     clazz = callPrep(self, method, obj, !noAccessCheck);
    681     if (clazz == NULL)
    682         return NULL;
    683     needPop = true;
    684 
    685     /* "ins" for new frame start at frame pointer plus locals */
    686     ins = ((s4*)self->interpSave.curFrame) +
    687         (method->registersSize - method->insSize);
    688     verifyCount = 0;
    689 
    690     //ALOGD("  FP is %p, INs live at >= %p", self->interpSave.curFrame, ins);
    691 
    692     /* put "this" pointer into in0 if appropriate */
    693     if (!dvmIsStaticMethod(method)) {
    694         assert(obj != NULL);
    695         *ins++ = (s4) obj;
    696         verifyCount++;
    697     }
    698 
    699     /*
    700      * Copy the args onto the stack.  Primitive types are converted when
    701      * necessary, and object types are verified.
    702      */
    703     DataObject** args = (DataObject**)(void*)argList->contents;
    704     ClassObject** types = (ClassObject**)(void*)params->contents;
    705     for (int i = 0; i < argListLength; i++) {
    706         int width = dvmConvertArgument(*args++, *types++, ins);
    707         if (width < 0) {
    708             dvmPopFrame(self);      // throw wants to pull PC out of stack
    709             needPop = false;
    710             throwArgumentTypeMismatch(i, *(types-1), *(args-1));
    711             goto bail;
    712         }
    713 
    714         ins += width;
    715         verifyCount += width;
    716     }
    717 
    718 #ifndef NDEBUG
    719     if (verifyCount != method->insSize) {
    720         ALOGE("Got vfycount=%d insSize=%d for %s.%s", verifyCount,
    721             method->insSize, clazz->descriptor, method->name);
    722         assert(false);
    723         goto bail;
    724     }
    725 #endif
    726 
    727     if (dvmIsNativeMethod(method)) {
    728         TRACE_METHOD_ENTER(self, method);
    729         /*
    730          * Because we leave no space for local variables, "curFrame" points
    731          * directly at the method arguments.
    732          */
    733         (*method->nativeFunc)((u4*)self->interpSave.curFrame, &retval,
    734                               method, self);
    735         TRACE_METHOD_EXIT(self, method);
    736     } else {
    737         dvmInterpret(self, method, &retval);
    738     }
    739 
    740     /*
    741      * Pop the frame immediately.  The "wrap" calls below can cause
    742      * allocations, and we don't want the GC to walk the now-dead frame.
    743      */
    744     dvmPopFrame(self);
    745     needPop = false;
    746 
    747     /*
    748      * If an exception is raised, wrap and replace.  This is necessary
    749      * because the invoked method could have thrown a checked exception
    750      * that the caller wasn't prepared for.
    751      *
    752      * We might be able to do this up in the interpreted code, but that will
    753      * leave us with a shortened stack trace in the top-level exception.
    754      */
    755     if (dvmCheckException(self)) {
    756         dvmWrapException("Ljava/lang/reflect/InvocationTargetException;");
    757     } else {
    758         /*
    759          * If this isn't a void method or constructor, convert the return type
    760          * to an appropriate object.
    761          *
    762          * We don't do this when an exception is raised because the value
    763          * in "retval" is undefined.
    764          */
    765         if (returnType != NULL) {
    766             retObj = (Object*)dvmBoxPrimitive(retval, returnType);
    767             dvmReleaseTrackedAlloc(retObj, NULL);
    768         }
    769     }
    770 
    771 bail:
    772     if (needPop) {
    773         dvmPopFrame(self);
    774     }
    775     return retObj;
    776 }
    777 
    778 struct LineNumFromPcContext {
    779     u4 address;
    780     u4 lineNum;
    781 };
    782 
    783 static int lineNumForPcCb(void *cnxt, u4 address, u4 lineNum)
    784 {
    785     LineNumFromPcContext *pContext = (LineNumFromPcContext *)cnxt;
    786 
    787     // We know that this callback will be called in
    788     // ascending address order, so keep going until we find
    789     // a match or we've just gone past it.
    790 
    791     if (address > pContext->address) {
    792         // The line number from the previous positions callback
    793         // wil be the final result.
    794         return 1;
    795     }
    796 
    797     pContext->lineNum = lineNum;
    798 
    799     return (address == pContext->address) ? 1 : 0;
    800 }
    801 
    802 /*
    803  * Determine the source file line number based on the program counter.
    804  * "pc" is an offset, in 16-bit units, from the start of the method's code.
    805  *
    806  * Returns -1 if no match was found (possibly because the source files were
    807  * compiled without "-g", so no line number information is present).
    808  * Returns -2 for native methods (as expected in exception traces).
    809  */
    810 int dvmLineNumFromPC(const Method* method, u4 relPc)
    811 {
    812     const DexCode* pDexCode = dvmGetMethodCode(method);
    813 
    814     if (pDexCode == NULL) {
    815         if (dvmIsNativeMethod(method) && !dvmIsAbstractMethod(method))
    816             return -2;
    817         return -1;      /* can happen for abstract method stub */
    818     }
    819 
    820     LineNumFromPcContext context;
    821     memset(&context, 0, sizeof(context));
    822     context.address = relPc;
    823     // A method with no line number info should return -1
    824     context.lineNum = -1;
    825 
    826     dexDecodeDebugInfo(method->clazz->pDvmDex->pDexFile, pDexCode,
    827             method->clazz->descriptor,
    828             method->prototype.protoIdx,
    829             method->accessFlags,
    830             lineNumForPcCb, NULL, &context);
    831 
    832     return context.lineNum;
    833 }
    834 
    835 /*
    836  * Compute the frame depth.
    837  *
    838  * Excludes "break" frames.
    839  */
    840 int dvmComputeExactFrameDepth(const void* fp)
    841 {
    842     int count = 0;
    843 
    844     for ( ; fp != NULL; fp = SAVEAREA_FROM_FP(fp)->prevFrame) {
    845         if (!dvmIsBreakFrame((u4*)fp))
    846             count++;
    847     }
    848 
    849     return count;
    850 }
    851 
    852 /*
    853  * Compute the "vague" frame depth, which is just a pointer subtraction.
    854  * The result is NOT an overly generous assessment of the number of
    855  * frames; the only meaningful use is to compare against the result of
    856  * an earlier invocation.
    857  *
    858  * Useful for implementing single-step debugger modes, which may need to
    859  * call this for every instruction.
    860  */
    861 int dvmComputeVagueFrameDepth(Thread* thread, const void* fp)
    862 {
    863     const u1* interpStackStart = thread->interpStackStart;
    864 
    865     assert((u1*) fp >= interpStackStart - thread->interpStackSize);
    866     assert((u1*) fp < interpStackStart);
    867     return interpStackStart - (u1*) fp;
    868 }
    869 
    870 /*
    871  * Get the calling frame.  Pass in the current fp.
    872  *
    873  * Skip "break" frames and reflection invoke frames.
    874  */
    875 void* dvmGetCallerFP(const void* curFrame)
    876 {
    877     void* caller = SAVEAREA_FROM_FP(curFrame)->prevFrame;
    878     StackSaveArea* saveArea;
    879 
    880 retry:
    881     if (dvmIsBreakFrame((u4*)caller)) {
    882         /* pop up one more */
    883         caller = SAVEAREA_FROM_FP(caller)->prevFrame;
    884         if (caller == NULL)
    885             return NULL;        /* hit the top */
    886 
    887         /*
    888          * If we got here by java.lang.reflect.Method.invoke(), we don't
    889          * want to return Method's class loader.  Shift up one and try
    890          * again.
    891          */
    892         saveArea = SAVEAREA_FROM_FP(caller);
    893         if (dvmIsReflectionMethod(saveArea->method)) {
    894             caller = saveArea->prevFrame;
    895             assert(caller != NULL);
    896             goto retry;
    897         }
    898     }
    899 
    900     return caller;
    901 }
    902 
    903 /*
    904  * Get the caller's class.  Pass in the current fp.
    905  *
    906  * This is used by e.g. java.lang.Class.
    907  */
    908 ClassObject* dvmGetCallerClass(const void* curFrame)
    909 {
    910     void* caller;
    911 
    912     caller = dvmGetCallerFP(curFrame);
    913     if (caller == NULL)
    914         return NULL;
    915 
    916     return SAVEAREA_FROM_FP(caller)->method->clazz;
    917 }
    918 
    919 /*
    920  * Get the caller's caller's class.  Pass in the current fp.
    921  *
    922  * This is used by e.g. java.lang.Class, which wants to know about the
    923  * class loader of the method that called it.
    924  */
    925 ClassObject* dvmGetCaller2Class(const void* curFrame)
    926 {
    927     void* caller = SAVEAREA_FROM_FP(curFrame)->prevFrame;
    928     void* callerCaller;
    929 
    930     /* at the top? */
    931     if (dvmIsBreakFrame((u4*)caller) &&
    932         SAVEAREA_FROM_FP(caller)->prevFrame == NULL)
    933         return NULL;
    934 
    935     /* go one more */
    936     callerCaller = dvmGetCallerFP(caller);
    937     if (callerCaller == NULL)
    938         return NULL;
    939 
    940     return SAVEAREA_FROM_FP(callerCaller)->method->clazz;
    941 }
    942 
    943 /*
    944  * Get the caller's caller's caller's class.  Pass in the current fp.
    945  *
    946  * This is used by e.g. java.lang.Class, which wants to know about the
    947  * class loader of the method that called it.
    948  */
    949 ClassObject* dvmGetCaller3Class(const void* curFrame)
    950 {
    951     void* caller = SAVEAREA_FROM_FP(curFrame)->prevFrame;
    952     int i;
    953 
    954     /* at the top? */
    955     if (dvmIsBreakFrame((u4*)caller) &&
    956         SAVEAREA_FROM_FP(caller)->prevFrame == NULL)
    957         return NULL;
    958 
    959     /* Walk up two frames if possible. */
    960     for (i = 0; i < 2; i++) {
    961         caller = dvmGetCallerFP(caller);
    962         if (caller == NULL)
    963             return NULL;
    964     }
    965 
    966     return SAVEAREA_FROM_FP(caller)->method->clazz;
    967 }
    968 
    969 /*
    970  * Fill a flat array of methods that comprise the current interpreter
    971  * stack trace.  Pass in the current frame ptr.  Break frames are
    972  * skipped, but reflection invocations are not.
    973  *
    974  * The current frame will be in element 0.
    975  */
    976 void dvmFillStackTraceArray(const void* fp, const Method** array, size_t length)
    977 {
    978     assert(fp != NULL);
    979     assert(array != NULL);
    980     size_t i = 0;
    981     while (fp != NULL) {
    982         if (!dvmIsBreakFrame((u4*)fp)) {
    983             assert(i < length);
    984             array[i++] = SAVEAREA_FROM_FP(fp)->method;
    985         }
    986         fp = SAVEAREA_FROM_FP(fp)->prevFrame;
    987     }
    988 }
    989 
    990 /*
    991  * Open up the reserved area and throw an exception.  The reserved area
    992  * should only be needed to create and initialize the exception itself.
    993  *
    994  * If we already opened it and we're continuing to overflow, abort the VM.
    995  *
    996  * We have to leave the "reserved" area open until the "catch" handler has
    997  * finished doing its processing.  This is because the catch handler may
    998  * need to resolve classes, which requires calling into the class loader if
    999  * the classes aren't already in the "initiating loader" list.
   1000  */
   1001 void dvmHandleStackOverflow(Thread* self, const Method* method)
   1002 {
   1003     /*
   1004      * Can we make the reserved area available?
   1005      */
   1006     if (self->stackOverflowed) {
   1007         /*
   1008          * Already did, nothing to do but bail.
   1009          */
   1010         ALOGE("DalvikVM: double-overflow of stack in threadid=%d; aborting",
   1011             self->threadId);
   1012         dvmDumpThread(self, false);
   1013         dvmAbort();
   1014     }
   1015 
   1016     /* open it up to the full range */
   1017     ALOGI("threadid=%d: stack overflow on call to %s.%s:%s",
   1018         self->threadId,
   1019         method->clazz->descriptor, method->name, method->shorty);
   1020     StackSaveArea* saveArea = SAVEAREA_FROM_FP(self->interpSave.curFrame);
   1021     ALOGI("  method requires %d+%d+%d=%d bytes, fp is %p (%d left)",
   1022         method->registersSize * 4, sizeof(StackSaveArea), method->outsSize * 4,
   1023         (method->registersSize + method->outsSize) * 4 + sizeof(StackSaveArea),
   1024         saveArea, (u1*) saveArea - self->interpStackEnd);
   1025     ALOGI("  expanding stack end (%p to %p)", self->interpStackEnd,
   1026         self->interpStackStart - self->interpStackSize);
   1027     //dvmDumpThread(self, false);
   1028     self->interpStackEnd = self->interpStackStart - self->interpStackSize;
   1029     self->stackOverflowed = true;
   1030 
   1031     /*
   1032      * If we were trying to throw an exception when the stack overflowed,
   1033      * we will blow up when doing the class lookup on StackOverflowError
   1034      * because of the pending exception.  So, we clear it and make it
   1035      * the cause of the SOE.
   1036      */
   1037     Object* excep = dvmGetException(self);
   1038     if (excep != NULL) {
   1039         ALOGW("Stack overflow while throwing exception");
   1040         dvmClearException(self);
   1041     }
   1042     dvmThrowChainedException(gDvm.exStackOverflowError, NULL, excep);
   1043 }
   1044 
   1045 /*
   1046  * Reduce the available stack size.  By this point we should have finished
   1047  * our overflow processing.
   1048  */
   1049 void dvmCleanupStackOverflow(Thread* self, const Object* exception)
   1050 {
   1051     const u1* newStackEnd;
   1052 
   1053     assert(self->stackOverflowed);
   1054 
   1055     if (exception->clazz != gDvm.exStackOverflowError) {
   1056         /* exception caused during SOE, not the SOE itself */
   1057         return;
   1058     }
   1059 
   1060     newStackEnd = (self->interpStackStart - self->interpStackSize)
   1061         + STACK_OVERFLOW_RESERVE;
   1062     if ((u1*)self->interpSave.curFrame <= newStackEnd) {
   1063         ALOGE("Can't shrink stack: curFrame is in reserved area (%p %p)",
   1064             self->interpStackEnd, self->interpSave.curFrame);
   1065         dvmDumpThread(self, false);
   1066         dvmAbort();
   1067     }
   1068 
   1069     self->interpStackEnd = newStackEnd;
   1070     self->stackOverflowed = false;
   1071 
   1072     ALOGI("Shrank stack (to %p, curFrame is %p)", self->interpStackEnd,
   1073         self->interpSave.curFrame);
   1074 }
   1075 
   1076 
   1077 /*
   1078  * Extract the object that is the target of a monitor-enter instruction
   1079  * in the top stack frame of "thread".
   1080  *
   1081  * The other thread might be alive, so this has to work carefully.
   1082  *
   1083  * The thread list lock must be held.
   1084  *
   1085  * Returns "true" if we successfully recover the object.  "*pOwner" will
   1086  * be NULL if we can't determine the owner for some reason (e.g. race
   1087  * condition on ownership transfer).
   1088  */
   1089 static bool extractMonitorEnterObject(Thread* thread, Object** pLockObj,
   1090     Thread** pOwner)
   1091 {
   1092     void* framePtr = thread->interpSave.curFrame;
   1093 
   1094     if (framePtr == NULL || dvmIsBreakFrame((u4*)framePtr))
   1095         return false;
   1096 
   1097     const StackSaveArea* saveArea = SAVEAREA_FROM_FP(framePtr);
   1098     const Method* method = saveArea->method;
   1099     const u2* currentPc = saveArea->xtra.currentPc;
   1100 
   1101     /* check Method* */
   1102     if (!dvmLinearAllocContains(method, sizeof(Method))) {
   1103         ALOGD("ExtrMon: method %p not valid", method);
   1104         return false;
   1105     }
   1106 
   1107     /* check currentPc */
   1108     u4 insnsSize = dvmGetMethodInsnsSize(method);
   1109     if (currentPc < method->insns ||
   1110         currentPc >= method->insns + insnsSize)
   1111     {
   1112         ALOGD("ExtrMon: insns %p not valid (%p - %p)",
   1113             currentPc, method->insns, method->insns + insnsSize);
   1114         return false;
   1115     }
   1116 
   1117     /* check the instruction */
   1118     if ((*currentPc & 0xff) != OP_MONITOR_ENTER) {
   1119         ALOGD("ExtrMon: insn at %p is not monitor-enter (0x%02x)",
   1120             currentPc, *currentPc & 0xff);
   1121         return false;
   1122     }
   1123 
   1124     /* get and check the register index */
   1125     unsigned int reg = *currentPc >> 8;
   1126     if (reg >= method->registersSize) {
   1127         ALOGD("ExtrMon: invalid register %d (max %d)",
   1128             reg, method->registersSize);
   1129         return false;
   1130     }
   1131 
   1132     /* get and check the object in that register */
   1133     u4* fp = (u4*) framePtr;
   1134     Object* obj = (Object*) fp[reg];
   1135     if (obj != NULL && !dvmIsHeapAddress(obj)) {
   1136         ALOGD("ExtrMon: invalid object %p at %p[%d]", obj, fp, reg);
   1137         return false;
   1138     }
   1139     *pLockObj = obj;
   1140 
   1141     /*
   1142      * Try to determine the object's lock holder; it's okay if this fails.
   1143      *
   1144      * We're assuming the thread list lock is already held by this thread.
   1145      * If it's not, we may be living dangerously if we have to scan through
   1146      * the thread list to find a match.  (The VM will generally be in a
   1147      * suspended state when executing here, so this is a minor concern
   1148      * unless we're dumping while threads are running, in which case there's
   1149      * a good chance of stuff blowing up anyway.)
   1150      */
   1151     *pOwner = dvmGetObjectLockHolder(obj);
   1152 
   1153     return true;
   1154 }
   1155 
   1156 static void printWaitMessage(const DebugOutputTarget* target, const char* detail, Object* obj,
   1157         Thread* thread)
   1158 {
   1159     std::string msg(StringPrintf("  - waiting %s <%p> ", detail, obj));
   1160 
   1161     if (obj->clazz != gDvm.classJavaLangClass) {
   1162         // I(16573)   - waiting on <0xf5feda38> (a java.util.LinkedList)
   1163         // I(16573)   - waiting on <0xf5ed54f8> (a java.lang.Class<java.lang.ref.ReferenceQueue>)
   1164         msg += "(a " + dvmHumanReadableType(obj) + ")";
   1165     }
   1166 
   1167     if (thread != NULL) {
   1168         std::string threadName(dvmGetThreadName(thread));
   1169         StringAppendF(&msg, " held by tid=%d (%s)", thread->threadId, threadName.c_str());
   1170     }
   1171 
   1172     dvmPrintDebugMessage(target, "%s\n", msg.c_str());
   1173 }
   1174 
   1175 /*
   1176  * Dump stack frames, starting from the specified frame and moving down.
   1177  *
   1178  * Each frame holds a pointer to the currently executing method, and the
   1179  * saved program counter from the caller ("previous" frame).  This means
   1180  * we don't have the PC for the current method on the stack, which is
   1181  * pretty reasonable since it's in the "PC register" for the VM.  Because
   1182  * exceptions need to show the correct line number we actually *do* have
   1183  * an updated version in the fame's "xtra.currentPc", but it's unreliable.
   1184  *
   1185  * Note "framePtr" could be NULL in rare circumstances.
   1186  */
   1187 static void dumpFrames(const DebugOutputTarget* target, void* framePtr,
   1188     Thread* thread)
   1189 {
   1190     const StackSaveArea* saveArea;
   1191     const Method* method;
   1192     int checkCount = 0;
   1193     const u2* currentPc = NULL;
   1194     bool first = true;
   1195 
   1196     /*
   1197      * We call functions that require us to be holding the thread list lock.
   1198      * It's probable that the caller has already done so, but it's not
   1199      * guaranteed.  If it's not locked, lock it now.
   1200      */
   1201     bool needThreadUnlock = dvmTryLockThreadList();
   1202 
   1203     /*
   1204      * The "currentPc" is updated whenever we execute an instruction that
   1205      * might throw an exception.  Show it here.
   1206      */
   1207     if (framePtr != NULL && !dvmIsBreakFrame((u4*)framePtr)) {
   1208         saveArea = SAVEAREA_FROM_FP(framePtr);
   1209 
   1210         if (saveArea->xtra.currentPc != NULL)
   1211             currentPc = saveArea->xtra.currentPc;
   1212     }
   1213 
   1214     while (framePtr != NULL) {
   1215         saveArea = SAVEAREA_FROM_FP(framePtr);
   1216         method = saveArea->method;
   1217 
   1218         if (dvmIsBreakFrame((u4*)framePtr)) {
   1219             //dvmPrintDebugMessage(target, "  (break frame)\n");
   1220         } else {
   1221             int relPc;
   1222 
   1223             if (currentPc != NULL)
   1224                 relPc = currentPc - saveArea->method->insns;
   1225             else
   1226                 relPc = -1;
   1227 
   1228             std::string methodName(dvmHumanReadableMethod(method, false));
   1229             if (dvmIsNativeMethod(method)) {
   1230                 dvmPrintDebugMessage(target, "  at %s(Native Method)\n",
   1231                         methodName.c_str());
   1232             } else {
   1233                 dvmPrintDebugMessage(target, "  at %s(%s:%s%d)\n",
   1234                         methodName.c_str(), dvmGetMethodSourceFile(method),
   1235                         (relPc >= 0 && first) ? "~" : "",
   1236                         relPc < 0 ? -1 : dvmLineNumFromPC(method, relPc));
   1237             }
   1238 
   1239             if (first) {
   1240                 /*
   1241                  * Decorate WAIT and MONITOR threads with some detail on
   1242                  * the first frame.
   1243                  *
   1244                  * warning: wait status not stable, even in suspend
   1245                  */
   1246                 if (thread->status == THREAD_WAIT ||
   1247                     thread->status == THREAD_TIMED_WAIT)
   1248                 {
   1249                     Monitor* mon = thread->waitMonitor;
   1250                     Object* obj = dvmGetMonitorObject(mon);
   1251                     if (obj != NULL) {
   1252                         Thread* joinThread = NULL;
   1253                         if (obj->clazz == gDvm.classJavaLangVMThread) {
   1254                             joinThread = dvmGetThreadFromThreadObject(obj);
   1255                         }
   1256                         if (joinThread == NULL) {
   1257                             joinThread = dvmGetObjectLockHolder(obj);
   1258                         }
   1259                         printWaitMessage(target, "on", obj, joinThread);
   1260                     }
   1261                 } else if (thread->status == THREAD_MONITOR) {
   1262                     Object* obj;
   1263                     Thread* owner;
   1264                     if (extractMonitorEnterObject(thread, &obj, &owner)) {
   1265                         printWaitMessage(target, "to lock", obj, owner);
   1266                     }
   1267                 }
   1268             }
   1269         }
   1270 
   1271         /*
   1272          * Get saved PC for previous frame.  There's no savedPc in a "break"
   1273          * frame, because that represents native or interpreted code
   1274          * invoked by the VM.  The saved PC is sitting in the "PC register",
   1275          * a local variable on the native stack.
   1276          */
   1277         currentPc = saveArea->savedPc;
   1278 
   1279         first = false;
   1280 
   1281         if (saveArea->prevFrame != NULL && saveArea->prevFrame <= framePtr) {
   1282             ALOGW("Warning: loop in stack trace at frame %d (%p -> %p)",
   1283                 checkCount, framePtr, saveArea->prevFrame);
   1284             break;
   1285         }
   1286         framePtr = saveArea->prevFrame;
   1287 
   1288         checkCount++;
   1289         if (checkCount > 300) {
   1290             dvmPrintDebugMessage(target,
   1291                 "  ***** printed %d frames, not showing any more\n",
   1292                 checkCount);
   1293             break;
   1294         }
   1295     }
   1296 
   1297     if (needThreadUnlock) {
   1298         dvmUnlockThreadList();
   1299     }
   1300 }
   1301 
   1302 
   1303 /*
   1304  * Dump the stack for the specified thread.
   1305  */
   1306 void dvmDumpThreadStack(const DebugOutputTarget* target, Thread* thread)
   1307 {
   1308     dumpFrames(target, thread->interpSave.curFrame, thread);
   1309 }
   1310 
   1311 /*
   1312  * Dump the stack for the specified thread, which is still running.
   1313  *
   1314  * This is very dangerous, because stack frames are being pushed on and
   1315  * popped off, and if the thread exits we'll be looking at freed memory.
   1316  * The plan here is to take a snapshot of the stack and then dump that
   1317  * to try to minimize the chances of catching it mid-update.  This should
   1318  * work reasonably well on a single-CPU system.
   1319  *
   1320  * There is a small chance that calling here will crash the VM.
   1321  */
   1322 void dvmDumpRunningThreadStack(const DebugOutputTarget* target, Thread* thread)
   1323 {
   1324     StackSaveArea* saveArea;
   1325     const u1* origStack;
   1326     u1* stackCopy = NULL;
   1327     int origSize, fpOffset;
   1328     void* fp;
   1329     int depthLimit = 200;
   1330 
   1331     if (thread == NULL || thread->interpSave.curFrame == NULL) {
   1332         dvmPrintDebugMessage(target,
   1333             "DumpRunning: Thread at %p has no curFrame (threadid=%d)\n",
   1334             thread, (thread != NULL) ? thread->threadId : 0);
   1335         return;
   1336     }
   1337 
   1338     /* wait for a full quantum */
   1339     sched_yield();
   1340 
   1341     /* copy the info we need, then the stack itself */
   1342     origSize = thread->interpStackSize;
   1343     origStack = (const u1*) thread->interpStackStart - origSize;
   1344     stackCopy = (u1*) malloc(origSize);
   1345     fpOffset = (u1*) thread->interpSave.curFrame - origStack;
   1346     memcpy(stackCopy, origStack, origSize);
   1347 
   1348     /*
   1349      * Run through the stack and rewrite the "prev" pointers.
   1350      */
   1351     //ALOGI("DR: fpOff=%d (from %p %p)",fpOffset, origStack,
   1352     //     thread->interpSave.curFrame);
   1353     fp = stackCopy + fpOffset;
   1354     while (true) {
   1355         int prevOffset;
   1356 
   1357         if (depthLimit-- < 0) {
   1358             /* we're probably screwed */
   1359             dvmPrintDebugMessage(target, "DumpRunning: depth limit hit\n");
   1360             dvmAbort();
   1361         }
   1362         saveArea = SAVEAREA_FROM_FP(fp);
   1363         if (saveArea->prevFrame == NULL)
   1364             break;
   1365 
   1366         prevOffset = (u1*) saveArea->prevFrame - origStack;
   1367         if (prevOffset < 0 || prevOffset > origSize) {
   1368             dvmPrintDebugMessage(target,
   1369                 "DumpRunning: bad offset found: %d (from %p %p)\n",
   1370                 prevOffset, origStack, saveArea->prevFrame);
   1371             saveArea->prevFrame = NULL;
   1372             break;
   1373         }
   1374 
   1375         saveArea->prevFrame = (u4*)(stackCopy + prevOffset);
   1376         fp = saveArea->prevFrame;
   1377     }
   1378 
   1379     /*
   1380      * We still need to pass the Thread for some monitor wait stuff.
   1381      */
   1382     dumpFrames(target, stackCopy + fpOffset, thread);
   1383     free(stackCopy);
   1384 }
   1385 
   1386 /*
   1387  * Dump the native stack for the specified thread.
   1388  */
   1389 void dvmDumpNativeStack(const DebugOutputTarget* target, pid_t tid)
   1390 {
   1391 #ifdef HAVE_ANDROID_OS
   1392     const size_t MAX_DEPTH = 32;
   1393     backtrace_frame_t backtrace[MAX_DEPTH];
   1394     ssize_t frames = unwind_backtrace_thread(tid, backtrace, 0, MAX_DEPTH);
   1395     if (frames > 0) {
   1396         backtrace_symbol_t backtrace_symbols[MAX_DEPTH];
   1397         get_backtrace_symbols(backtrace, frames, backtrace_symbols);
   1398 
   1399         for (size_t i = 0; i < size_t(frames); i++) {
   1400             char line[MAX_BACKTRACE_LINE_LENGTH];
   1401             format_backtrace_line(i, &backtrace[i], &backtrace_symbols[i],
   1402                     line, MAX_BACKTRACE_LINE_LENGTH);
   1403             dvmPrintDebugMessage(target, "  %s\n", line);
   1404         }
   1405 
   1406         free_backtrace_symbols(backtrace_symbols, frames);
   1407     } else {
   1408         dvmPrintDebugMessage(target, "  (native backtrace unavailable)\n");
   1409     }
   1410 #endif
   1411 }
   1412