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