• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  * Stacks and their uses (e.g. native --> interpreted method calls).
18  *
19  * See the majestic ASCII art in Stack.h.
20  */
21 #include "Dalvik.h"
22 #include "jni.h"
23 
24 #include <stdlib.h>
25 #include <stdarg.h>
26 
27 /*
28  * Initialize the interpreter stack in a new thread.
29  *
30  * Currently this doesn't do much, since we don't need to zero out the
31  * stack (and we really don't want to if it was created with mmap).
32  */
dvmInitInterpStack(Thread * thread,int stackSize)33 bool dvmInitInterpStack(Thread* thread, int stackSize)
34 {
35     assert(thread->interpStackStart != NULL);
36 
37     assert(thread->curFrame == NULL);
38 
39     return true;
40 }
41 
42 /*
43  * We're calling an interpreted method from an internal VM function or
44  * via reflection.
45  *
46  * Push a frame for an interpreted method onto the stack.  This is only
47  * used when calling into interpreted code from native code.  (The
48  * interpreter does its own stack frame manipulation for interp-->interp
49  * calls.)
50  *
51  * The size we need to reserve is the sum of parameters, local variables,
52  * saved goodies, and outbound parameters.
53  *
54  * We start by inserting a "break" frame, which ensures that the interpreter
55  * hands control back to us after the function we call returns or an
56  * uncaught exception is thrown.
57  */
dvmPushInterpFrame(Thread * self,const Method * method)58 static bool dvmPushInterpFrame(Thread* self, const Method* method)
59 {
60     StackSaveArea* saveBlock;
61     StackSaveArea* breakSaveBlock;
62     int stackReq;
63     u1* stackPtr;
64 
65     assert(!dvmIsNativeMethod(method));
66     assert(!dvmIsAbstractMethod(method));
67 
68     stackReq = method->registersSize * 4        // params + locals
69                 + sizeof(StackSaveArea) * 2     // break frame + regular frame
70                 + method->outsSize * 4;         // args to other methods
71 
72     if (self->curFrame != NULL)
73         stackPtr = (u1*) SAVEAREA_FROM_FP(self->curFrame);
74     else
75         stackPtr = self->interpStackStart;
76 
77     if (stackPtr - stackReq < self->interpStackEnd) {
78         /* not enough space */
79         LOGW("Stack overflow on call to interp "
80              "(req=%d top=%p cur=%p size=%d %s.%s)\n",
81             stackReq, self->interpStackStart, self->curFrame,
82             self->interpStackSize, method->clazz->descriptor, method->name);
83         dvmHandleStackOverflow(self);
84         assert(dvmCheckException(self));
85         return false;
86     }
87 
88     /*
89      * Shift the stack pointer down, leaving space for the function's
90      * args/registers and save area.
91      */
92     stackPtr -= sizeof(StackSaveArea);
93     breakSaveBlock = (StackSaveArea*)stackPtr;
94     stackPtr -= method->registersSize * 4 + sizeof(StackSaveArea);
95     saveBlock = (StackSaveArea*) stackPtr;
96 
97 #if !defined(NDEBUG) && !defined(PAD_SAVE_AREA)
98     /* debug -- memset the new stack, unless we want valgrind's help */
99     memset(stackPtr - (method->outsSize*4), 0xaf, stackReq);
100 #endif
101 #ifdef EASY_GDB
102     breakSaveBlock->prevSave = FP_FROM_SAVEAREA(self->curFrame);
103     saveBlock->prevSave = breakSaveBlock;
104 #endif
105 
106     breakSaveBlock->prevFrame = self->curFrame;
107     breakSaveBlock->savedPc = NULL;             // not required
108     breakSaveBlock->xtra.localRefCookie = 0;    // not required
109     breakSaveBlock->method = NULL;
110     saveBlock->prevFrame = FP_FROM_SAVEAREA(breakSaveBlock);
111     saveBlock->savedPc = NULL;                  // not required
112     saveBlock->xtra.currentPc = NULL;           // not required?
113     saveBlock->method = method;
114 
115     LOGVV("PUSH frame: old=%p new=%p (size=%d)\n",
116         self->curFrame, FP_FROM_SAVEAREA(saveBlock),
117         (u1*)self->curFrame - (u1*)FP_FROM_SAVEAREA(saveBlock));
118 
119     self->curFrame = FP_FROM_SAVEAREA(saveBlock);
120 
121     return true;
122 }
123 
124 /*
125  * We're calling a JNI native method from an internal VM fuction or
126  * via reflection.  This is also used to create the "fake" native-method
127  * frames at the top of the interpreted stack.
128  *
129  * This actually pushes two frames; the first is a "break" frame.
130  *
131  * The top frame has additional space for JNI local reference tracking.
132  */
dvmPushJNIFrame(Thread * self,const Method * method)133 bool dvmPushJNIFrame(Thread* self, const Method* method)
134 {
135     StackSaveArea* saveBlock;
136     StackSaveArea* breakSaveBlock;
137     int stackReq;
138     u1* stackPtr;
139 
140     assert(dvmIsNativeMethod(method));
141 
142     stackReq = method->registersSize * 4        // params only
143                 + sizeof(StackSaveArea) * 2;    // break frame + regular frame
144 
145     if (self->curFrame != NULL)
146         stackPtr = (u1*) SAVEAREA_FROM_FP(self->curFrame);
147     else
148         stackPtr = self->interpStackStart;
149 
150     if (stackPtr - stackReq < self->interpStackEnd) {
151         /* not enough space */
152         LOGW("Stack overflow on call to native "
153              "(req=%d top=%p cur=%p size=%d '%s')\n",
154             stackReq, self->interpStackStart, self->curFrame,
155             self->interpStackSize, method->name);
156         dvmHandleStackOverflow(self);
157         assert(dvmCheckException(self));
158         return false;
159     }
160 
161     /*
162      * Shift the stack pointer down, leaving space for just the stack save
163      * area for the break frame, then shift down farther for the full frame.
164      * We leave space for the method args, which are copied in later.
165      */
166     stackPtr -= sizeof(StackSaveArea);
167     breakSaveBlock = (StackSaveArea*)stackPtr;
168     stackPtr -= method->registersSize * 4 + sizeof(StackSaveArea);
169     saveBlock = (StackSaveArea*) stackPtr;
170 
171 #if !defined(NDEBUG) && !defined(PAD_SAVE_AREA)
172     /* debug -- memset the new stack */
173     memset(stackPtr, 0xaf, stackReq);
174 #endif
175 #ifdef EASY_GDB
176     if (self->curFrame == NULL)
177         breakSaveBlock->prevSave = NULL;
178     else
179         breakSaveBlock->prevSave = FP_FROM_SAVEAREA(self->curFrame);
180     saveBlock->prevSave = breakSaveBlock;
181 #endif
182 
183     breakSaveBlock->prevFrame = self->curFrame;
184     breakSaveBlock->savedPc = NULL;             // not required
185     breakSaveBlock->xtra.localRefCookie = 0;    // not required
186     breakSaveBlock->method = NULL;
187     saveBlock->prevFrame = FP_FROM_SAVEAREA(breakSaveBlock);
188     saveBlock->savedPc = NULL;                  // not required
189 #ifdef USE_INDIRECT_REF
190     saveBlock->xtra.localRefCookie = self->jniLocalRefTable.segmentState.all;
191 #else
192     saveBlock->xtra.localRefCookie = self->jniLocalRefTable.nextEntry;
193 #endif
194     saveBlock->method = method;
195 
196     LOGVV("PUSH JNI frame: old=%p new=%p (size=%d)\n",
197         self->curFrame, FP_FROM_SAVEAREA(saveBlock),
198         (u1*)self->curFrame - (u1*)FP_FROM_SAVEAREA(saveBlock));
199 
200     self->curFrame = FP_FROM_SAVEAREA(saveBlock);
201 
202     return true;
203 }
204 
205 /*
206  * This is used by the JNI PushLocalFrame call.  We push a new frame onto
207  * the stack that has no ins, outs, or locals, and no break frame above it.
208  * It's strictly used for tracking JNI local refs, and will be popped off
209  * by dvmPopFrame if it's not removed explicitly.
210  */
dvmPushLocalFrame(Thread * self,const Method * method)211 bool dvmPushLocalFrame(Thread* self, const Method* method)
212 {
213     StackSaveArea* saveBlock;
214     int stackReq;
215     u1* stackPtr;
216 
217     assert(dvmIsNativeMethod(method));
218 
219     stackReq = sizeof(StackSaveArea);       // regular frame
220 
221     assert(self->curFrame != NULL);
222     stackPtr = (u1*) SAVEAREA_FROM_FP(self->curFrame);
223 
224     if (stackPtr - stackReq < self->interpStackEnd) {
225         /* not enough space; let JNI throw the exception */
226         LOGW("Stack overflow on PushLocal "
227              "(req=%d top=%p cur=%p size=%d '%s')\n",
228             stackReq, self->interpStackStart, self->curFrame,
229             self->interpStackSize, method->name);
230         dvmHandleStackOverflow(self);
231         assert(dvmCheckException(self));
232         return false;
233     }
234 
235     /*
236      * Shift the stack pointer down, leaving space for just the stack save
237      * area for the break frame, then shift down farther for the full frame.
238      */
239     stackPtr -= sizeof(StackSaveArea);
240     saveBlock = (StackSaveArea*) stackPtr;
241 
242 #if !defined(NDEBUG) && !defined(PAD_SAVE_AREA)
243     /* debug -- memset the new stack */
244     memset(stackPtr, 0xaf, stackReq);
245 #endif
246 #ifdef EASY_GDB
247     saveBlock->prevSave = FP_FROM_SAVEAREA(self->curFrame);
248 #endif
249 
250     saveBlock->prevFrame = self->curFrame;
251     saveBlock->savedPc = NULL;                  // not required
252 #ifdef USE_INDIRECT_REF
253     saveBlock->xtra.localRefCookie = self->jniLocalRefTable.segmentState.all;
254 #else
255     saveBlock->xtra.localRefCookie = self->jniLocalRefTable.nextEntry;
256 #endif
257     saveBlock->method = method;
258 
259     LOGVV("PUSH JNI local frame: old=%p new=%p (size=%d)\n",
260         self->curFrame, FP_FROM_SAVEAREA(saveBlock),
261         (u1*)self->curFrame - (u1*)FP_FROM_SAVEAREA(saveBlock));
262 
263     self->curFrame = FP_FROM_SAVEAREA(saveBlock);
264 
265     return true;
266 }
267 
268 /*
269  * Pop one frame pushed on by JNI PushLocalFrame.
270  *
271  * If we've gone too far, the previous frame is either a break frame or
272  * an interpreted frame.  Either way, the method pointer won't match.
273  */
dvmPopLocalFrame(Thread * self)274 bool dvmPopLocalFrame(Thread* self)
275 {
276     StackSaveArea* saveBlock = SAVEAREA_FROM_FP(self->curFrame);
277 
278     assert(!dvmIsBreakFrame(self->curFrame));
279     if (saveBlock->method != SAVEAREA_FROM_FP(saveBlock->prevFrame)->method) {
280         /*
281          * The previous frame doesn't have the same method pointer -- we've
282          * been asked to pop too much.
283          */
284         assert(dvmIsBreakFrame(saveBlock->prevFrame) ||
285                !dvmIsNativeMethod(
286                        SAVEAREA_FROM_FP(saveBlock->prevFrame)->method));
287         return false;
288     }
289 
290     LOGVV("POP JNI local frame: removing %s, now %s\n",
291         saveBlock->method->name,
292         SAVEAREA_FROM_FP(saveBlock->prevFrame)->method->name);
293     dvmPopJniLocals(self, saveBlock);
294     self->curFrame = saveBlock->prevFrame;
295 
296     return true;
297 }
298 
299 /*
300  * Pop a frame we added.  There should be one method frame and one break
301  * frame.
302  *
303  * If JNI Push/PopLocalFrame calls were mismatched, we might end up
304  * popping multiple method frames before we find the break.
305  *
306  * Returns "false" if there was no frame to pop.
307  */
dvmPopFrame(Thread * self)308 static bool dvmPopFrame(Thread* self)
309 {
310     StackSaveArea* saveBlock;
311 
312     if (self->curFrame == NULL)
313         return false;
314 
315     saveBlock = SAVEAREA_FROM_FP(self->curFrame);
316     assert(!dvmIsBreakFrame(self->curFrame));
317 
318     /*
319      * Remove everything up to the break frame.  If this was a call into
320      * native code, pop the JNI local references table.
321      */
322     while (saveBlock->prevFrame != NULL && saveBlock->method != NULL) {
323         /* probably a native->native JNI call */
324 
325         if (dvmIsNativeMethod(saveBlock->method)) {
326             LOGVV("Popping JNI stack frame for %s.%s%s\n",
327                 saveBlock->method->clazz->descriptor,
328                 saveBlock->method->name,
329                 (SAVEAREA_FROM_FP(saveBlock->prevFrame)->method == NULL) ?
330                 "" : " (JNI local)");
331             assert(saveBlock->xtra.localRefCookie != 0);
332             //assert(saveBlock->xtra.localRefCookie >= self->jniLocalRefTable.table &&
333             //    saveBlock->xtra.localRefCookie <=self->jniLocalRefTable.nextEntry);
334 
335             dvmPopJniLocals(self, saveBlock);
336         }
337 
338         saveBlock = SAVEAREA_FROM_FP(saveBlock->prevFrame);
339     }
340     if (saveBlock->method != NULL) {
341         LOGE("PopFrame missed the break\n");
342         assert(false);
343         dvmAbort();     // stack trashed -- nowhere to go in this thread
344     }
345 
346     LOGVV("POP frame: cur=%p new=%p\n",
347         self->curFrame, saveBlock->prevFrame);
348 
349     self->curFrame = saveBlock->prevFrame;
350     return true;
351 }
352 
353 /*
354  * Common code for dvmCallMethodV/A and dvmInvokeMethod.
355  *
356  * Pushes a call frame on, advancing self->curFrame.
357  */
callPrep(Thread * self,const Method * method,Object * obj,bool checkAccess)358 static ClassObject* callPrep(Thread* self, const Method* method, Object* obj,
359     bool checkAccess)
360 {
361     ClassObject* clazz;
362 
363 #ifndef NDEBUG
364     if (self->status != THREAD_RUNNING) {
365         LOGW("threadid=%d: status=%d on call to %s.%s -\n",
366             self->threadId, self->status,
367             method->clazz->descriptor, method->name);
368     }
369 #endif
370 
371     assert(self != NULL);
372     assert(method != NULL);
373 
374     if (obj != NULL)
375         clazz = obj->clazz;
376     else
377         clazz = method->clazz;
378 
379     IF_LOGVV() {
380         char* desc = dexProtoCopyMethodDescriptor(&method->prototype);
381         LOGVV("thread=%d native code calling %s.%s %s\n", self->threadId,
382             clazz->descriptor, method->name, desc);
383         free(desc);
384     }
385 
386     if (checkAccess) {
387         /* needed for java.lang.reflect.Method.invoke */
388         if (!dvmCheckMethodAccess(dvmGetCaller2Class(self->curFrame),
389                 method))
390         {
391             /* note this throws IAException, not IAError */
392             dvmThrowException("Ljava/lang/IllegalAccessException;",
393                 "access to method denied");
394             return NULL;
395         }
396     }
397 
398     /*
399      * Push a call frame on.  If there isn't enough room for ins, locals,
400      * outs, and the saved state, it will throw an exception.
401      *
402      * This updates self->curFrame.
403      */
404     if (dvmIsNativeMethod(method)) {
405         /* native code calling native code the hard way */
406         if (!dvmPushJNIFrame(self, method)) {
407             assert(dvmCheckException(self));
408             return NULL;
409         }
410     } else {
411         /* native code calling interpreted code */
412         if (!dvmPushInterpFrame(self, method)) {
413             assert(dvmCheckException(self));
414             return NULL;
415         }
416     }
417 
418     return clazz;
419 }
420 
421 /*
422  * Issue a method call.
423  *
424  * Pass in NULL for "obj" on calls to static methods.
425  *
426  * (Note this can't be inlined because it takes a variable number of args.)
427  */
dvmCallMethod(Thread * self,const Method * method,Object * obj,JValue * pResult,...)428 void dvmCallMethod(Thread* self, const Method* method, Object* obj,
429     JValue* pResult, ...)
430 {
431     JValue result;
432 
433     va_list args;
434     va_start(args, pResult);
435     dvmCallMethodV(self, method, obj, false, pResult, args);
436     va_end(args);
437 }
438 
439 /*
440  * Issue a method call with a variable number of arguments.  We process
441  * the contents of "args" by scanning the method signature.
442  *
443  * Pass in NULL for "obj" on calls to static methods.
444  *
445  * We don't need to take the class as an argument because, in Dalvik,
446  * we don't need to worry about static synchronized methods.
447  */
dvmCallMethodV(Thread * self,const Method * method,Object * obj,bool fromJni,JValue * pResult,va_list args)448 void dvmCallMethodV(Thread* self, const Method* method, Object* obj,
449     bool fromJni, JValue* pResult, va_list args)
450 {
451     const char* desc = &(method->shorty[1]); // [0] is the return type.
452     int verifyCount = 0;
453     ClassObject* clazz;
454     u4* ins;
455 
456     clazz = callPrep(self, method, obj, false);
457     if (clazz == NULL)
458         return;
459 
460     /* "ins" for new frame start at frame pointer plus locals */
461     ins = ((u4*)self->curFrame) + (method->registersSize - method->insSize);
462 
463     //LOGD("  FP is %p, INs live at >= %p\n", self->curFrame, ins);
464 
465     /* put "this" pointer into in0 if appropriate */
466     if (!dvmIsStaticMethod(method)) {
467 #ifdef WITH_EXTRA_OBJECT_VALIDATION
468         assert(obj != NULL && dvmIsValidObject(obj));
469 #endif
470         *ins++ = (u4) obj;
471         verifyCount++;
472     }
473 
474     JNIEnv* env = self->jniEnv;
475     while (*desc != '\0') {
476         switch (*(desc++)) {
477             case 'D': case 'J': {
478                 u8 val = va_arg(args, u8);
479                 memcpy(ins, &val, 8);       // EABI prevents direct store
480                 ins += 2;
481                 verifyCount += 2;
482                 break;
483             }
484             case 'F': {
485                 /* floats were normalized to doubles; convert back */
486                 float f = (float) va_arg(args, double);
487                 *ins++ = dvmFloatToU4(f);
488                 verifyCount++;
489                 break;
490             }
491             case 'L': {     /* 'shorty' descr uses L for all refs, incl array */
492                 void* argObj = va_arg(args, void*);
493                 assert(obj == NULL || dvmIsValidObject(obj));
494                 if (fromJni)
495                     *ins++ = (u4) dvmDecodeIndirectRef(env, argObj);
496                 else
497                     *ins++ = (u4) argObj;
498                 verifyCount++;
499                 break;
500             }
501             default: {
502                 /* Z B C S I -- all passed as 32-bit integers */
503                 *ins++ = va_arg(args, u4);
504                 verifyCount++;
505                 break;
506             }
507         }
508     }
509 
510 #ifndef NDEBUG
511     if (verifyCount != method->insSize) {
512         LOGE("Got vfycount=%d insSize=%d for %s.%s\n", verifyCount,
513             method->insSize, clazz->descriptor, method->name);
514         assert(false);
515         goto bail;
516     }
517 #endif
518 
519     //dvmDumpThreadStack(dvmThreadSelf());
520 
521     if (dvmIsNativeMethod(method)) {
522 #ifdef WITH_PROFILER
523         TRACE_METHOD_ENTER(self, method);
524 #endif
525         /*
526          * Because we leave no space for local variables, "curFrame" points
527          * directly at the method arguments.
528          */
529         (*method->nativeFunc)(self->curFrame, pResult, method, self);
530 #ifdef WITH_PROFILER
531         TRACE_METHOD_EXIT(self, method);
532 #endif
533     } else {
534         dvmInterpret(self, method, pResult);
535     }
536 
537 bail:
538     dvmPopFrame(self);
539 }
540 
541 /*
542  * Issue a method call with arguments provided in an array.  We process
543  * the contents of "args" by scanning the method signature.
544  *
545  * The values were likely placed into an uninitialized jvalue array using
546  * the field specifiers, which means that sub-32-bit fields (e.g. short,
547  * boolean) may not have 32 or 64 bits of valid data.  This is different
548  * from the varargs invocation where the C compiler does a widening
549  * conversion when calling a function.  As a result, we have to be a
550  * little more precise when pulling stuff out.
551  *
552  * "args" may be NULL if the method has no arguments.
553  */
dvmCallMethodA(Thread * self,const Method * method,Object * obj,bool fromJni,JValue * pResult,const jvalue * args)554 void dvmCallMethodA(Thread* self, const Method* method, Object* obj,
555     bool fromJni, JValue* pResult, const jvalue* args)
556 {
557     const char* desc = &(method->shorty[1]); // [0] is the return type.
558     int verifyCount = 0;
559     ClassObject* clazz;
560     u4* ins;
561 
562     clazz = callPrep(self, method, obj, false);
563     if (clazz == NULL)
564         return;
565 
566     /* "ins" for new frame start at frame pointer plus locals */
567     ins = ((u4*)self->curFrame) + (method->registersSize - method->insSize);
568 
569     /* put "this" pointer into in0 if appropriate */
570     if (!dvmIsStaticMethod(method)) {
571         assert(obj != NULL);
572         *ins++ = (u4) obj;              /* obj is a "real" ref */
573         verifyCount++;
574     }
575 
576     JNIEnv* env = self->jniEnv;
577     while (*desc != '\0') {
578         switch (*desc++) {
579         case 'D':                       /* 64-bit quantity; have to use */
580         case 'J':                       /*  memcpy() in case of mis-alignment */
581             memcpy(ins, &args->j, 8);
582             ins += 2;
583             verifyCount++;              /* this needs an extra push */
584             break;
585         case 'L':                       /* includes array refs */
586             if (fromJni)
587                 *ins++ = (u4) dvmDecodeIndirectRef(env, args->l);
588             else
589                 *ins++ = (u4) args->l;
590             break;
591         case 'F':
592         case 'I':
593             *ins++ = args->i;           /* full 32 bits */
594             break;
595         case 'S':
596             *ins++ = args->s;           /* 16 bits, sign-extended */
597             break;
598         case 'C':
599             *ins++ = args->c;           /* 16 bits, unsigned */
600             break;
601         case 'B':
602             *ins++ = args->b;           /* 8 bits, sign-extended */
603             break;
604         case 'Z':
605             *ins++ = args->z;           /* 8 bits, zero or non-zero */
606             break;
607         default:
608             LOGE("Invalid char %c in short signature of %s.%s\n",
609                 *(desc-1), clazz->descriptor, method->name);
610             assert(false);
611             goto bail;
612         }
613 
614         verifyCount++;
615         args++;
616     }
617 
618 #ifndef NDEBUG
619     if (verifyCount != method->insSize) {
620         LOGE("Got vfycount=%d insSize=%d for %s.%s\n", verifyCount,
621             method->insSize, clazz->descriptor, method->name);
622         assert(false);
623         goto bail;
624     }
625 #endif
626 
627     if (dvmIsNativeMethod(method)) {
628 #ifdef WITH_PROFILER
629         TRACE_METHOD_ENTER(self, method);
630 #endif
631         /*
632          * Because we leave no space for local variables, "curFrame" points
633          * directly at the method arguments.
634          */
635         (*method->nativeFunc)(self->curFrame, pResult, method, self);
636 #ifdef WITH_PROFILER
637         TRACE_METHOD_EXIT(self, method);
638 #endif
639     } else {
640         dvmInterpret(self, method, pResult);
641     }
642 
643 bail:
644     dvmPopFrame(self);
645 }
646 
647 /*
648  * Invoke a method, using the specified arguments and return type, through
649  * one of the reflection interfaces.  Could be a virtual or direct method
650  * (including constructors).  Used for reflection.
651  *
652  * Deals with boxing/unboxing primitives and performs widening conversions.
653  *
654  * "invokeObj" will be null for a static method.
655  *
656  * If the invocation returns with an exception raised, we have to wrap it.
657  */
dvmInvokeMethod(Object * obj,const Method * method,ArrayObject * argList,ArrayObject * params,ClassObject * returnType,bool noAccessCheck)658 Object* dvmInvokeMethod(Object* obj, const Method* method,
659     ArrayObject* argList, ArrayObject* params, ClassObject* returnType,
660     bool noAccessCheck)
661 {
662     ClassObject* clazz;
663     Object* retObj = NULL;
664     Thread* self = dvmThreadSelf();
665     s4* ins;
666     int verifyCount, argListLength;
667     JValue retval;
668 
669     /* verify arg count */
670     if (argList != NULL)
671         argListLength = argList->length;
672     else
673         argListLength = 0;
674     if (argListLength != (int) params->length) {
675         LOGI("invoke: expected %d args, received %d args\n",
676             params->length, argListLength);
677         dvmThrowException("Ljava/lang/IllegalArgumentException;",
678             "wrong number of arguments");
679         return NULL;
680     }
681 
682     clazz = callPrep(self, method, obj, !noAccessCheck);
683     if (clazz == NULL)
684         return NULL;
685 
686     /* "ins" for new frame start at frame pointer plus locals */
687     ins = ((s4*)self->curFrame) + (method->registersSize - method->insSize);
688     verifyCount = 0;
689 
690     //LOGD("  FP is %p, INs live at >= %p\n", self->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;
704     ClassObject** types;
705     int i;
706 
707     args = (DataObject**) argList->contents;
708     types = (ClassObject**) params->contents;
709     for (i = 0; i < argListLength; i++) {
710         int width;
711 
712         width = dvmConvertArgument(*args++, *types++, ins);
713         if (width < 0) {
714             if (*(args-1) != NULL) {
715                 LOGV("invoke: type mismatch on arg %d ('%s' '%s')\n",
716                     i, (*(args-1))->obj.clazz->descriptor,
717                     (*(types-1))->descriptor);
718             }
719             dvmPopFrame(self);      // throw wants to pull PC out of stack
720             dvmThrowException("Ljava/lang/IllegalArgumentException;",
721                 "argument type mismatch");
722             goto bail_popped;
723         }
724 
725         ins += width;
726         verifyCount += width;
727     }
728 
729     if (verifyCount != method->insSize) {
730         LOGE("Got vfycount=%d insSize=%d for %s.%s\n", verifyCount,
731             method->insSize, clazz->descriptor, method->name);
732         assert(false);
733         goto bail;
734     }
735     //dvmDumpThreadStack(dvmThreadSelf());
736 
737     if (dvmIsNativeMethod(method)) {
738 #ifdef WITH_PROFILER
739         TRACE_METHOD_ENTER(self, method);
740 #endif
741         /*
742          * Because we leave no space for local variables, "curFrame" points
743          * directly at the method arguments.
744          */
745         (*method->nativeFunc)(self->curFrame, &retval, method, self);
746 #ifdef WITH_PROFILER
747         TRACE_METHOD_EXIT(self, method);
748 #endif
749     } else {
750         dvmInterpret(self, method, &retval);
751     }
752 
753     /*
754      * If an exception is raised, wrap and replace.  This is necessary
755      * because the invoked method could have thrown a checked exception
756      * that the caller wasn't prepared for.
757      *
758      * We might be able to do this up in the interpreted code, but that will
759      * leave us with a shortened stack trace in the top-level exception.
760      */
761     if (dvmCheckException(self)) {
762         dvmWrapException("Ljava/lang/reflect/InvocationTargetException;");
763     } else {
764         /*
765          * If this isn't a void method or constructor, convert the return type
766          * to an appropriate object.
767          *
768          * We don't do this when an exception is raised because the value
769          * in "retval" is undefined.
770          */
771         if (returnType != NULL) {
772             retObj = (Object*)dvmWrapPrimitive(retval, returnType);
773             dvmReleaseTrackedAlloc(retObj, NULL);
774         }
775     }
776 
777 bail:
778     dvmPopFrame(self);
779 bail_popped:
780     return retObj;
781 }
782 
783 typedef struct LineNumFromPcContext {
784     u4 address;
785     u4 lineNum;
786 } LineNumFromPcContext;
787 
lineNumForPcCb(void * cnxt,u4 address,u4 lineNum)788 static 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  */
dvmLineNumFromPC(const Method * method,u4 relPc)815 int 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  */
dvmComputeExactFrameDepth(const void * fp)845 int 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  */
dvmComputeVagueFrameDepth(Thread * thread,const void * fp)866 int dvmComputeVagueFrameDepth(Thread* thread, const void* fp)
867 {
868     const u1* interpStackStart = thread->interpStackStart;
869     const u1* interpStackBottom = interpStackStart - thread->interpStackSize;
870 
871     assert((u1*) fp >= interpStackBottom && (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  */
dvmGetCallerFP(const void * curFrame)880 void* dvmGetCallerFP(const void* curFrame)
881 {
882     void* caller = SAVEAREA_FROM_FP(curFrame)->prevFrame;
883     StackSaveArea* saveArea;
884 
885 retry:
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  */
dvmGetCallerClass(const void * curFrame)913 ClassObject* 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  */
dvmGetCaller2Class(const void * curFrame)930 ClassObject* 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  */
dvmGetCaller3Class(const void * curFrame)953 ClassObject* 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  */
dvmCreateStackTraceArray(const void * fp,const Method *** pArray,int * pLength)984 bool 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  */
dvmHandleStackOverflow(Thread * self)1017 void dvmHandleStackOverflow(Thread* self)
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("Stack overflow, expanding (%p to %p)\n", self->interpStackEnd,
1034         self->interpStackStart - self->interpStackSize);
1035     //dvmDumpThread(self, false);
1036     self->interpStackEnd = self->interpStackStart - self->interpStackSize;
1037     self->stackOverflowed = true;
1038 
1039     /*
1040      * If we were trying to throw an exception when the stack overflowed,
1041      * we will blow up when doing the class lookup on StackOverflowError
1042      * because of the pending exception.  So, we clear it and make it
1043      * the cause of the SOE.
1044      */
1045     Object* excep = dvmGetException(self);
1046     if (excep != NULL) {
1047         LOGW("Stack overflow while throwing exception\n");
1048         dvmClearException(self);
1049     }
1050     dvmThrowChainedException("Ljava/lang/StackOverflowError;", NULL, excep);
1051 }
1052 
1053 /*
1054  * Reduce the available stack size.  By this point we should have finished
1055  * our overflow processing.
1056  */
dvmCleanupStackOverflow(Thread * self)1057 void dvmCleanupStackOverflow(Thread* self)
1058 {
1059     const u1* newStackEnd;
1060 
1061     assert(self->stackOverflowed);
1062 
1063     newStackEnd = (self->interpStackStart - self->interpStackSize)
1064         + STACK_OVERFLOW_RESERVE;
1065     if ((u1*)self->curFrame <= newStackEnd) {
1066         LOGE("Can't shrink stack: curFrame is in reserved area (%p %p)\n",
1067             self->interpStackEnd, self->curFrame);
1068         dvmDumpThread(self, false);
1069         dvmAbort();
1070     }
1071 
1072     self->interpStackEnd = newStackEnd;
1073     self->stackOverflowed = false;
1074 
1075     LOGI("Shrank stack (to %p, curFrame is %p)\n", self->interpStackEnd,
1076         self->curFrame);
1077 }
1078 
1079 
1080 /*
1081  * Dump stack frames, starting from the specified frame and moving down.
1082  *
1083  * Each frame holds a pointer to the currently executing method, and the
1084  * saved program counter from the caller ("previous" frame).  This means
1085  * we don't have the PC for the current method on the stack, which is
1086  * pretty reasonable since it's in the "PC register" for the VM.  Because
1087  * exceptions need to show the correct line number we actually *do* have
1088  * an updated version in the fame's "xtra.currentPc", but it's unreliable.
1089  *
1090  * Note "framePtr" could be NULL in rare circumstances.
1091  */
dumpFrames(const DebugOutputTarget * target,void * framePtr,Thread * thread)1092 static void dumpFrames(const DebugOutputTarget* target, void* framePtr,
1093     Thread* thread)
1094 {
1095     const StackSaveArea* saveArea;
1096     const Method* method;
1097     int checkCount = 0;
1098     const u2* currentPc = NULL;
1099     bool first = true;
1100 
1101     /*
1102      * The "currentPc" is updated whenever we execute an instruction that
1103      * might throw an exception.  Show it here.
1104      */
1105     if (framePtr != NULL && !dvmIsBreakFrame(framePtr)) {
1106         saveArea = SAVEAREA_FROM_FP(framePtr);
1107 
1108         if (saveArea->xtra.currentPc != NULL)
1109             currentPc = saveArea->xtra.currentPc;
1110     }
1111 
1112     while (framePtr != NULL) {
1113         saveArea = SAVEAREA_FROM_FP(framePtr);
1114         method = saveArea->method;
1115 
1116         if (dvmIsBreakFrame(framePtr)) {
1117             //dvmPrintDebugMessage(target, "  (break frame)\n");
1118         } else {
1119             int relPc;
1120 
1121             if (currentPc != NULL)
1122                 relPc = currentPc - saveArea->method->insns;
1123             else
1124                 relPc = -1;
1125 
1126             char* className = dvmDescriptorToDot(method->clazz->descriptor);
1127             if (dvmIsNativeMethod(method))
1128                 dvmPrintDebugMessage(target,
1129                     "  at %s.%s(Native Method)\n", className, method->name);
1130             else {
1131                 dvmPrintDebugMessage(target,
1132                     "  at %s.%s(%s:%s%d)\n",
1133                     className, method->name, dvmGetMethodSourceFile(method),
1134                     (relPc >= 0 && first) ? "~" : "",
1135                     relPc < 0 ? -1 : dvmLineNumFromPC(method, relPc));
1136             }
1137             free(className);
1138 
1139             if (first &&
1140                 (thread->status == THREAD_WAIT ||
1141                  thread->status == THREAD_TIMED_WAIT))
1142             {
1143                 /* warning: wait status not stable, even in suspend */
1144                 Monitor* mon = thread->waitMonitor;
1145                 Object* obj = dvmGetMonitorObject(mon);
1146                 if (obj != NULL) {
1147                     className = dvmDescriptorToDot(obj->clazz->descriptor);
1148                     dvmPrintDebugMessage(target,
1149                         "  - waiting on <%p> (a %s)\n", mon, className);
1150                     free(className);
1151                 }
1152             }
1153 
1154         }
1155 
1156         /*
1157          * Get saved PC for previous frame.  There's no savedPc in a "break"
1158          * frame, because that represents native or interpreted code
1159          * invoked by the VM.  The saved PC is sitting in the "PC register",
1160          * a local variable on the native stack.
1161          */
1162         currentPc = saveArea->savedPc;
1163 
1164         first = false;
1165 
1166         if (saveArea->prevFrame != NULL && saveArea->prevFrame <= framePtr) {
1167             LOGW("Warning: loop in stack trace at frame %d (%p -> %p)\n",
1168                 checkCount, framePtr, saveArea->prevFrame);
1169             break;
1170         }
1171         framePtr = saveArea->prevFrame;
1172 
1173         checkCount++;
1174         if (checkCount > 300) {
1175             dvmPrintDebugMessage(target,
1176                 "  ***** printed %d frames, not showing any more\n",
1177                 checkCount);
1178             break;
1179         }
1180     }
1181     dvmPrintDebugMessage(target, "\n");
1182 }
1183 
1184 
1185 /*
1186  * Dump the stack for the specified thread.
1187  */
dvmDumpThreadStack(const DebugOutputTarget * target,Thread * thread)1188 void dvmDumpThreadStack(const DebugOutputTarget* target, Thread* thread)
1189 {
1190     dumpFrames(target, thread->curFrame, thread);
1191 }
1192 
1193 /*
1194  * Dump the stack for the specified thread, which is still running.
1195  *
1196  * This is very dangerous, because stack frames are being pushed on and
1197  * popped off, and if the thread exits we'll be looking at freed memory.
1198  * The plan here is to take a snapshot of the stack and then dump that
1199  * to try to minimize the chances of catching it mid-update.  This should
1200  * work reasonably well on a single-CPU system.
1201  *
1202  * There is a small chance that calling here will crash the VM.
1203  */
dvmDumpRunningThreadStack(const DebugOutputTarget * target,Thread * thread)1204 void dvmDumpRunningThreadStack(const DebugOutputTarget* target, Thread* thread)
1205 {
1206     StackSaveArea* saveArea;
1207     const u1* origStack;
1208     u1* stackCopy = NULL;
1209     int origSize, fpOffset;
1210     void* fp;
1211     int depthLimit = 200;
1212 
1213     if (thread == NULL || thread->curFrame == NULL) {
1214         dvmPrintDebugMessage(target,
1215             "DumpRunning: Thread at %p has no curFrame (threadid=%d)\n",
1216             thread, (thread != NULL) ? thread->threadId : 0);
1217         return;
1218     }
1219 
1220     /* wait for a full quantum */
1221     sched_yield();
1222 
1223     /* copy the info we need, then the stack itself */
1224     origSize = thread->interpStackSize;
1225     origStack = (const u1*) thread->interpStackStart - origSize;
1226     stackCopy = (u1*) malloc(origSize);
1227     fpOffset = (u1*) thread->curFrame - origStack;
1228     memcpy(stackCopy, origStack, origSize);
1229 
1230     /*
1231      * Run through the stack and rewrite the "prev" pointers.
1232      */
1233     //LOGI("DR: fpOff=%d (from %p %p)\n",fpOffset, origStack, thread->curFrame);
1234     fp = stackCopy + fpOffset;
1235     while (true) {
1236         int prevOffset;
1237 
1238         if (depthLimit-- < 0) {
1239             /* we're probably screwed */
1240             dvmPrintDebugMessage(target, "DumpRunning: depth limit hit\n");
1241             dvmAbort();
1242         }
1243         saveArea = SAVEAREA_FROM_FP(fp);
1244         if (saveArea->prevFrame == NULL)
1245             break;
1246 
1247         prevOffset = (u1*) saveArea->prevFrame - origStack;
1248         if (prevOffset < 0 || prevOffset > origSize) {
1249             dvmPrintDebugMessage(target,
1250                 "DumpRunning: bad offset found: %d (from %p %p)\n",
1251                 prevOffset, origStack, saveArea->prevFrame);
1252             saveArea->prevFrame = NULL;
1253             break;
1254         }
1255 
1256         saveArea->prevFrame = stackCopy + prevOffset;
1257         fp = saveArea->prevFrame;
1258     }
1259 
1260     /*
1261      * We still need to pass the Thread for some monitor wait stuff.
1262      */
1263     dumpFrames(target, stackCopy + fpOffset, thread);
1264     free(stackCopy);
1265 }
1266 
1267