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 JValue result; 433 434 va_list args; 435 va_start(args, pResult); 436 dvmCallMethodV(self, method, obj, false, pResult, args); 437 va_end(args); 438} 439 440/* 441 * Issue a method call with a variable number of arguments. We process 442 * the contents of "args" by scanning the method signature. 443 * 444 * Pass in NULL for "obj" on calls to static methods. 445 * 446 * We don't need to take the class as an argument because, in Dalvik, 447 * we don't need to worry about static synchronized methods. 448 */ 449void dvmCallMethodV(Thread* self, const Method* method, Object* obj, 450 bool fromJni, JValue* pResult, va_list args) 451{ 452 const char* desc = &(method->shorty[1]); // [0] is the return type. 453 int verifyCount = 0; 454 ClassObject* clazz; 455 u4* ins; 456 457 clazz = callPrep(self, method, obj, false); 458 if (clazz == NULL) 459 return; 460 461 /* "ins" for new frame start at frame pointer plus locals */ 462 ins = ((u4*)self->curFrame) + (method->registersSize - method->insSize); 463 464 //LOGD(" FP is %p, INs live at >= %p\n", self->curFrame, ins); 465 466 /* put "this" pointer into in0 if appropriate */ 467 if (!dvmIsStaticMethod(method)) { 468#ifdef WITH_EXTRA_OBJECT_VALIDATION 469 assert(obj != NULL && dvmIsValidObject(obj)); 470#endif 471 *ins++ = (u4) obj; 472 verifyCount++; 473 } 474 475 JNIEnv* env = self->jniEnv; 476 while (*desc != '\0') { 477 switch (*(desc++)) { 478 case 'D': case 'J': { 479 u8 val = va_arg(args, u8); 480 memcpy(ins, &val, 8); // EABI prevents direct store 481 ins += 2; 482 verifyCount += 2; 483 break; 484 } 485 case 'F': { 486 /* floats were normalized to doubles; convert back */ 487 float f = (float) va_arg(args, double); 488 *ins++ = dvmFloatToU4(f); 489 verifyCount++; 490 break; 491 } 492 case 'L': { /* 'shorty' descr uses L for all refs, incl array */ 493 void* argObj = va_arg(args, void*); 494 assert(obj == NULL || dvmIsValidObject(obj)); 495 if (fromJni) 496 *ins++ = (u4) dvmDecodeIndirectRef(env, argObj); 497 else 498 *ins++ = (u4) argObj; 499 verifyCount++; 500 break; 501 } 502 default: { 503 /* Z B C S I -- all passed as 32-bit integers */ 504 *ins++ = va_arg(args, u4); 505 verifyCount++; 506 break; 507 } 508 } 509 } 510 511#ifndef NDEBUG 512 if (verifyCount != method->insSize) { 513 LOGE("Got vfycount=%d insSize=%d for %s.%s\n", verifyCount, 514 method->insSize, clazz->descriptor, method->name); 515 assert(false); 516 goto bail; 517 } 518#endif 519 520 //dvmDumpThreadStack(dvmThreadSelf()); 521 522 if (dvmIsNativeMethod(method)) { 523#ifdef WITH_PROFILER 524 TRACE_METHOD_ENTER(self, method); 525#endif 526 /* 527 * Because we leave no space for local variables, "curFrame" points 528 * directly at the method arguments. 529 */ 530 (*method->nativeFunc)(self->curFrame, pResult, method, self); 531#ifdef WITH_PROFILER 532 TRACE_METHOD_EXIT(self, method); 533#endif 534 } else { 535 dvmInterpret(self, method, pResult); 536 } 537 538bail: 539 dvmPopFrame(self); 540} 541 542/* 543 * Issue a method call with arguments provided in an array. We process 544 * the contents of "args" by scanning the method signature. 545 * 546 * The values were likely placed into an uninitialized jvalue array using 547 * the field specifiers, which means that sub-32-bit fields (e.g. short, 548 * boolean) may not have 32 or 64 bits of valid data. This is different 549 * from the varargs invocation where the C compiler does a widening 550 * conversion when calling a function. As a result, we have to be a 551 * little more precise when pulling stuff out. 552 * 553 * "args" may be NULL if the method has no arguments. 554 */ 555void dvmCallMethodA(Thread* self, const Method* method, Object* obj, 556 bool fromJni, JValue* pResult, const jvalue* args) 557{ 558 const char* desc = &(method->shorty[1]); // [0] is the return type. 559 int verifyCount = 0; 560 ClassObject* clazz; 561 u4* ins; 562 563 clazz = callPrep(self, method, obj, false); 564 if (clazz == NULL) 565 return; 566 567 /* "ins" for new frame start at frame pointer plus locals */ 568 ins = ((u4*)self->curFrame) + (method->registersSize - method->insSize); 569 570 /* put "this" pointer into in0 if appropriate */ 571 if (!dvmIsStaticMethod(method)) { 572 assert(obj != NULL); 573 *ins++ = (u4) obj; /* obj is a "real" ref */ 574 verifyCount++; 575 } 576 577 JNIEnv* env = self->jniEnv; 578 while (*desc != '\0') { 579 switch (*desc++) { 580 case 'D': /* 64-bit quantity; have to use */ 581 case 'J': /* memcpy() in case of mis-alignment */ 582 memcpy(ins, &args->j, 8); 583 ins += 2; 584 verifyCount++; /* this needs an extra push */ 585 break; 586 case 'L': /* includes array refs */ 587 if (fromJni) 588 *ins++ = (u4) dvmDecodeIndirectRef(env, args->l); 589 else 590 *ins++ = (u4) args->l; 591 break; 592 case 'F': 593 case 'I': 594 *ins++ = args->i; /* full 32 bits */ 595 break; 596 case 'S': 597 *ins++ = args->s; /* 16 bits, sign-extended */ 598 break; 599 case 'C': 600 *ins++ = args->c; /* 16 bits, unsigned */ 601 break; 602 case 'B': 603 *ins++ = args->b; /* 8 bits, sign-extended */ 604 break; 605 case 'Z': 606 *ins++ = args->z; /* 8 bits, zero or non-zero */ 607 break; 608 default: 609 LOGE("Invalid char %c in short signature of %s.%s\n", 610 *(desc-1), clazz->descriptor, method->name); 611 assert(false); 612 goto bail; 613 } 614 615 verifyCount++; 616 args++; 617 } 618 619#ifndef NDEBUG 620 if (verifyCount != method->insSize) { 621 LOGE("Got vfycount=%d insSize=%d for %s.%s\n", verifyCount, 622 method->insSize, clazz->descriptor, method->name); 623 assert(false); 624 goto bail; 625 } 626#endif 627 628 if (dvmIsNativeMethod(method)) { 629#ifdef WITH_PROFILER 630 TRACE_METHOD_ENTER(self, method); 631#endif 632 /* 633 * Because we leave no space for local variables, "curFrame" points 634 * directly at the method arguments. 635 */ 636 (*method->nativeFunc)(self->curFrame, pResult, method, self); 637#ifdef WITH_PROFILER 638 TRACE_METHOD_EXIT(self, method); 639#endif 640 } else { 641 dvmInterpret(self, method, pResult); 642 } 643 644bail: 645 dvmPopFrame(self); 646} 647 648/* 649 * Invoke a method, using the specified arguments and return type, through 650 * one of the reflection interfaces. Could be a virtual or direct method 651 * (including constructors). Used for reflection. 652 * 653 * Deals with boxing/unboxing primitives and performs widening conversions. 654 * 655 * "invokeObj" will be null for a static method. 656 * 657 * If the invocation returns with an exception raised, we have to wrap it. 658 */ 659Object* dvmInvokeMethod(Object* obj, const Method* method, 660 ArrayObject* argList, ArrayObject* params, ClassObject* returnType, 661 bool noAccessCheck) 662{ 663 ClassObject* clazz; 664 Object* retObj = NULL; 665 Thread* self = dvmThreadSelf(); 666 s4* ins; 667 int verifyCount, argListLength; 668 JValue retval; 669 670 /* verify arg count */ 671 if (argList != NULL) 672 argListLength = argList->length; 673 else 674 argListLength = 0; 675 if (argListLength != (int) params->length) { 676 LOGI("invoke: expected %d args, received %d args\n", 677 params->length, argListLength); 678 dvmThrowException("Ljava/lang/IllegalArgumentException;", 679 "wrong number of arguments"); 680 return NULL; 681 } 682 683 clazz = callPrep(self, method, obj, !noAccessCheck); 684 if (clazz == NULL) 685 return NULL; 686 687 /* "ins" for new frame start at frame pointer plus locals */ 688 ins = ((s4*)self->curFrame) + (method->registersSize - method->insSize); 689 verifyCount = 0; 690 691 //LOGD(" FP is %p, INs live at >= %p\n", self->curFrame, ins); 692 693 /* put "this" pointer into in0 if appropriate */ 694 if (!dvmIsStaticMethod(method)) { 695 assert(obj != NULL); 696 *ins++ = (s4) obj; 697 verifyCount++; 698 } 699 700 /* 701 * Copy the args onto the stack. Primitive types are converted when 702 * necessary, and object types are verified. 703 */ 704 DataObject** args; 705 ClassObject** types; 706 int i; 707 708 args = (DataObject**) argList->contents; 709 types = (ClassObject**) params->contents; 710 for (i = 0; i < argListLength; i++) { 711 int width; 712 713 width = dvmConvertArgument(*args++, *types++, ins); 714 if (width < 0) { 715 if (*(args-1) != NULL) { 716 LOGV("invoke: type mismatch on arg %d ('%s' '%s')\n", 717 i, (*(args-1))->obj.clazz->descriptor, 718 (*(types-1))->descriptor); 719 } 720 dvmPopFrame(self); // throw wants to pull PC out of stack 721 dvmThrowException("Ljava/lang/IllegalArgumentException;", 722 "argument type mismatch"); 723 goto bail_popped; 724 } 725 726 ins += width; 727 verifyCount += width; 728 } 729 730 if (verifyCount != method->insSize) { 731 LOGE("Got vfycount=%d insSize=%d for %s.%s\n", verifyCount, 732 method->insSize, clazz->descriptor, method->name); 733 assert(false); 734 goto bail; 735 } 736 //dvmDumpThreadStack(dvmThreadSelf()); 737 738 if (dvmIsNativeMethod(method)) { 739#ifdef WITH_PROFILER 740 TRACE_METHOD_ENTER(self, method); 741#endif 742 /* 743 * Because we leave no space for local variables, "curFrame" points 744 * directly at the method arguments. 745 */ 746 (*method->nativeFunc)(self->curFrame, &retval, method, self); 747#ifdef WITH_PROFILER 748 TRACE_METHOD_EXIT(self, method); 749#endif 750 } else { 751 dvmInterpret(self, method, &retval); 752 } 753 754 /* 755 * If an exception is raised, wrap and replace. This is necessary 756 * because the invoked method could have thrown a checked exception 757 * that the caller wasn't prepared for. 758 * 759 * We might be able to do this up in the interpreted code, but that will 760 * leave us with a shortened stack trace in the top-level exception. 761 */ 762 if (dvmCheckException(self)) { 763 dvmWrapException("Ljava/lang/reflect/InvocationTargetException;"); 764 } else { 765 /* 766 * If this isn't a void method or constructor, convert the return type 767 * to an appropriate object. 768 * 769 * We don't do this when an exception is raised because the value 770 * in "retval" is undefined. 771 */ 772 if (returnType != NULL) { 773 retObj = (Object*)dvmWrapPrimitive(retval, returnType); 774 dvmReleaseTrackedAlloc(retObj, NULL); 775 } 776 } 777 778bail: 779 dvmPopFrame(self); 780bail_popped: 781 return retObj; 782} 783 784typedef struct LineNumFromPcContext { 785 u4 address; 786 u4 lineNum; 787} LineNumFromPcContext; 788 789static int lineNumForPcCb(void *cnxt, u4 address, u4 lineNum) 790{ 791 LineNumFromPcContext *pContext = (LineNumFromPcContext *)cnxt; 792 793 // We know that this callback will be called in 794 // ascending address order, so keep going until we find 795 // a match or we've just gone past it. 796 797 if (address > pContext->address) { 798 // The line number from the previous positions callback 799 // wil be the final result. 800 return 1; 801 } 802 803 pContext->lineNum = lineNum; 804 805 return (address == pContext->address) ? 1 : 0; 806} 807 808/* 809 * Determine the source file line number based on the program counter. 810 * "pc" is an offset, in 16-bit units, from the start of the method's code. 811 * 812 * Returns -1 if no match was found (possibly because the source files were 813 * compiled without "-g", so no line number information is present). 814 * Returns -2 for native methods (as expected in exception traces). 815 */ 816int dvmLineNumFromPC(const Method* method, u4 relPc) 817{ 818 const DexCode* pDexCode = dvmGetMethodCode(method); 819 820 if (pDexCode == NULL) { 821 if (dvmIsNativeMethod(method) && !dvmIsAbstractMethod(method)) 822 return -2; 823 return -1; /* can happen for abstract method stub */ 824 } 825 826 LineNumFromPcContext context; 827 memset(&context, 0, sizeof(context)); 828 context.address = relPc; 829 // A method with no line number info should return -1 830 context.lineNum = -1; 831 832 dexDecodeDebugInfo(method->clazz->pDvmDex->pDexFile, pDexCode, 833 method->clazz->descriptor, 834 method->prototype.protoIdx, 835 method->accessFlags, 836 lineNumForPcCb, NULL, &context); 837 838 return context.lineNum; 839} 840 841/* 842 * Compute the frame depth. 843 * 844 * Excludes "break" frames. 845 */ 846int dvmComputeExactFrameDepth(const void* fp) 847{ 848 int count = 0; 849 850 for ( ; fp != NULL; fp = SAVEAREA_FROM_FP(fp)->prevFrame) { 851 if (!dvmIsBreakFrame(fp)) 852 count++; 853 } 854 855 return count; 856} 857 858/* 859 * Compute the "vague" frame depth, which is just a pointer subtraction. 860 * The result is NOT an overly generous assessment of the number of 861 * frames; the only meaningful use is to compare against the result of 862 * an earlier invocation. 863 * 864 * Useful for implementing single-step debugger modes, which may need to 865 * call this for every instruction. 866 */ 867int dvmComputeVagueFrameDepth(Thread* thread, const void* fp) 868{ 869 const u1* interpStackStart = thread->interpStackStart; 870 const u1* interpStackBottom = interpStackStart - thread->interpStackSize; 871 872 assert((u1*) fp >= interpStackBottom && (u1*) fp < interpStackStart); 873 return interpStackStart - (u1*) fp; 874} 875 876/* 877 * Get the calling frame. Pass in the current fp. 878 * 879 * Skip "break" frames and reflection invoke frames. 880 */ 881void* dvmGetCallerFP(const void* curFrame) 882{ 883 void* caller = SAVEAREA_FROM_FP(curFrame)->prevFrame; 884 StackSaveArea* saveArea; 885 886retry: 887 if (dvmIsBreakFrame(caller)) { 888 /* pop up one more */ 889 caller = SAVEAREA_FROM_FP(caller)->prevFrame; 890 if (caller == NULL) 891 return NULL; /* hit the top */ 892 893 /* 894 * If we got here by java.lang.reflect.Method.invoke(), we don't 895 * want to return Method's class loader. Shift up one and try 896 * again. 897 */ 898 saveArea = SAVEAREA_FROM_FP(caller); 899 if (dvmIsReflectionMethod(saveArea->method)) { 900 caller = saveArea->prevFrame; 901 assert(caller != NULL); 902 goto retry; 903 } 904 } 905 906 return caller; 907} 908 909/* 910 * Get the caller's class. Pass in the current fp. 911 * 912 * This is used by e.g. java.lang.Class. 913 */ 914ClassObject* dvmGetCallerClass(const void* curFrame) 915{ 916 void* caller; 917 918 caller = dvmGetCallerFP(curFrame); 919 if (caller == NULL) 920 return NULL; 921 922 return SAVEAREA_FROM_FP(caller)->method->clazz; 923} 924 925/* 926 * Get the caller's caller's class. Pass in the current fp. 927 * 928 * This is used by e.g. java.lang.Class, which wants to know about the 929 * class loader of the method that called it. 930 */ 931ClassObject* dvmGetCaller2Class(const void* curFrame) 932{ 933 void* caller = SAVEAREA_FROM_FP(curFrame)->prevFrame; 934 void* callerCaller; 935 936 /* at the top? */ 937 if (dvmIsBreakFrame(caller) && SAVEAREA_FROM_FP(caller)->prevFrame == NULL) 938 return NULL; 939 940 /* go one more */ 941 callerCaller = dvmGetCallerFP(caller); 942 if (callerCaller == NULL) 943 return NULL; 944 945 return SAVEAREA_FROM_FP(callerCaller)->method->clazz; 946} 947 948/* 949 * Get the caller's caller's caller's class. Pass in the current fp. 950 * 951 * This is used by e.g. java.lang.Class, which wants to know about the 952 * class loader of the method that called it. 953 */ 954ClassObject* dvmGetCaller3Class(const void* curFrame) 955{ 956 void* caller = SAVEAREA_FROM_FP(curFrame)->prevFrame; 957 int i; 958 959 /* at the top? */ 960 if (dvmIsBreakFrame(caller) && SAVEAREA_FROM_FP(caller)->prevFrame == NULL) 961 return NULL; 962 963 /* Walk up two frames if possible. */ 964 for (i = 0; i < 2; i++) { 965 caller = dvmGetCallerFP(caller); 966 if (caller == NULL) 967 return NULL; 968 } 969 970 return SAVEAREA_FROM_FP(caller)->method->clazz; 971} 972 973/* 974 * Create a flat array of methods that comprise the current interpreter 975 * stack trace. Pass in the current frame ptr. 976 * 977 * Allocates a new array and fills it with method pointers. Break frames 978 * are skipped, but reflection invocations are not. The caller must free 979 * "*pArray". 980 * 981 * The current frame will be in element 0. 982 * 983 * Returns "true" on success, "false" on failure (e.g. malloc failed). 984 */ 985bool dvmCreateStackTraceArray(const void* fp, const Method*** pArray, 986 int* pLength) 987{ 988 const Method** array; 989 int idx, depth; 990 991 depth = dvmComputeExactFrameDepth(fp); 992 array = (const Method**) malloc(depth * sizeof(Method*)); 993 if (array == NULL) 994 return false; 995 996 for (idx = 0; fp != NULL; fp = SAVEAREA_FROM_FP(fp)->prevFrame) { 997 if (!dvmIsBreakFrame(fp)) 998 array[idx++] = SAVEAREA_FROM_FP(fp)->method; 999 } 1000 assert(idx == depth); 1001 1002 *pArray = array; 1003 *pLength = depth; 1004 return true; 1005} 1006 1007/* 1008 * Open up the reserved area and throw an exception. The reserved area 1009 * should only be needed to create and initialize the exception itself. 1010 * 1011 * If we already opened it and we're continuing to overflow, abort the VM. 1012 * 1013 * We have to leave the "reserved" area open until the "catch" handler has 1014 * finished doing its processing. This is because the catch handler may 1015 * need to resolve classes, which requires calling into the class loader if 1016 * the classes aren't already in the "initiating loader" list. 1017 */ 1018void dvmHandleStackOverflow(Thread* self, const Method* method) 1019{ 1020 /* 1021 * Can we make the reserved area available? 1022 */ 1023 if (self->stackOverflowed) { 1024 /* 1025 * Already did, nothing to do but bail. 1026 */ 1027 LOGE("DalvikVM: double-overflow of stack in threadid=%d; aborting\n", 1028 self->threadId); 1029 dvmDumpThread(self, false); 1030 dvmAbort(); 1031 } 1032 1033 /* open it up to the full range */ 1034 LOGI("threadid=%d: stack overflow on call to %s.%s:%s\n", 1035 self->threadId, 1036 method->clazz->descriptor, method->name, method->shorty); 1037 StackSaveArea* saveArea = SAVEAREA_FROM_FP(self->curFrame); 1038 LOGI(" method requires %d+%d+%d=%d bytes, fp is %p (%d left)\n", 1039 method->registersSize * 4, sizeof(StackSaveArea), method->outsSize * 4, 1040 (method->registersSize + method->outsSize) * 4 + sizeof(StackSaveArea), 1041 saveArea, (u1*) saveArea - self->interpStackEnd); 1042 LOGI(" expanding stack end (%p to %p)\n", self->interpStackEnd, 1043 self->interpStackStart - self->interpStackSize); 1044 //dvmDumpThread(self, false); 1045 self->interpStackEnd = self->interpStackStart - self->interpStackSize; 1046 self->stackOverflowed = true; 1047 1048 /* 1049 * If we were trying to throw an exception when the stack overflowed, 1050 * we will blow up when doing the class lookup on StackOverflowError 1051 * because of the pending exception. So, we clear it and make it 1052 * the cause of the SOE. 1053 */ 1054 Object* excep = dvmGetException(self); 1055 if (excep != NULL) { 1056 LOGW("Stack overflow while throwing exception\n"); 1057 dvmClearException(self); 1058 } 1059 dvmThrowChainedExceptionByClass(gDvm.classJavaLangStackOverflowError, 1060 NULL, excep); 1061} 1062 1063/* 1064 * Reduce the available stack size. By this point we should have finished 1065 * our overflow processing. 1066 */ 1067void dvmCleanupStackOverflow(Thread* self, const Object* exception) 1068{ 1069 const u1* newStackEnd; 1070 1071 assert(self->stackOverflowed); 1072 1073 if (exception->clazz != gDvm.classJavaLangStackOverflowError) { 1074 /* exception caused during SOE, not the SOE itself */ 1075 return; 1076 } 1077 1078 newStackEnd = (self->interpStackStart - self->interpStackSize) 1079 + STACK_OVERFLOW_RESERVE; 1080 if ((u1*)self->curFrame <= newStackEnd) { 1081 LOGE("Can't shrink stack: curFrame is in reserved area (%p %p)\n", 1082 self->interpStackEnd, self->curFrame); 1083 dvmDumpThread(self, false); 1084 dvmAbort(); 1085 } 1086 1087 self->interpStackEnd = newStackEnd; 1088 self->stackOverflowed = false; 1089 1090 LOGI("Shrank stack (to %p, curFrame is %p)\n", self->interpStackEnd, 1091 self->curFrame); 1092} 1093 1094 1095/* 1096 * Extract the object that is the target of a monitor-enter instruction 1097 * in the top stack frame of "thread". 1098 * 1099 * The other thread might be alive, so this has to work carefully. 1100 * 1101 * We assume the thread list lock is currently held. 1102 * 1103 * Returns "true" if we successfully recover the object. "*pOwner" will 1104 * be NULL if we can't determine the owner for some reason (e.g. race 1105 * condition on ownership transfer). 1106 */ 1107static bool extractMonitorEnterObject(Thread* thread, Object** pLockObj, 1108 Thread** pOwner) 1109{ 1110 void* framePtr = thread->curFrame; 1111 1112 if (framePtr == NULL || dvmIsBreakFrame(framePtr)) 1113 return false; 1114 1115 const StackSaveArea* saveArea = SAVEAREA_FROM_FP(framePtr); 1116 const Method* method = saveArea->method; 1117 const u2* currentPc = saveArea->xtra.currentPc; 1118 1119 /* check Method* */ 1120 if (!dvmLinearAllocContains(method, sizeof(Method))) { 1121 LOGD("ExtrMon: method %p not valid\n", method); 1122 return false; 1123 } 1124 1125 /* check currentPc */ 1126 u4 insnsSize = dvmGetMethodInsnsSize(method); 1127 if (currentPc < method->insns || 1128 currentPc >= method->insns + insnsSize) 1129 { 1130 LOGD("ExtrMon: insns %p not valid (%p - %p)\n", 1131 currentPc, method->insns, method->insns + insnsSize); 1132 return false; 1133 } 1134 1135 /* check the instruction */ 1136 if ((*currentPc & 0xff) != OP_MONITOR_ENTER) { 1137 LOGD("ExtrMon: insn at %p is not monitor-enter (0x%02x)\n", 1138 currentPc, *currentPc & 0xff); 1139 return false; 1140 } 1141 1142 /* get and check the register index */ 1143 unsigned int reg = *currentPc >> 8; 1144 if (reg >= method->registersSize) { 1145 LOGD("ExtrMon: invalid register %d (max %d)\n", 1146 reg, method->registersSize); 1147 return false; 1148 } 1149 1150 /* get and check the object in that register */ 1151 u4* fp = (u4*) framePtr; 1152 Object* obj = (Object*) fp[reg]; 1153 if (!dvmIsValidObject(obj)) { 1154 LOGD("ExtrMon: invalid object %p at %p[%d]\n", obj, fp, reg); 1155 return false; 1156 } 1157 *pLockObj = obj; 1158 1159 /* 1160 * Try to determine the object's lock holder; it's okay if this fails. 1161 * 1162 * We're assuming the thread list lock is already held by this thread. 1163 * If it's not, we may be living dangerously if we have to scan through 1164 * the thread list to find a match. (The VM will generally be in a 1165 * suspended state when executing here, so this is a minor concern 1166 * unless we're dumping while threads are running, in which case there's 1167 * a good chance of stuff blowing up anyway.) 1168 */ 1169 *pOwner = dvmGetObjectLockHolder(obj); 1170 1171 return true; 1172} 1173 1174/* 1175 * Dump stack frames, starting from the specified frame and moving down. 1176 * 1177 * Each frame holds a pointer to the currently executing method, and the 1178 * saved program counter from the caller ("previous" frame). This means 1179 * we don't have the PC for the current method on the stack, which is 1180 * pretty reasonable since it's in the "PC register" for the VM. Because 1181 * exceptions need to show the correct line number we actually *do* have 1182 * an updated version in the fame's "xtra.currentPc", but it's unreliable. 1183 * 1184 * Note "framePtr" could be NULL in rare circumstances. 1185 */ 1186static void dumpFrames(const DebugOutputTarget* target, void* framePtr, 1187 Thread* thread) 1188{ 1189 const StackSaveArea* saveArea; 1190 const Method* method; 1191 int checkCount = 0; 1192 const u2* currentPc = NULL; 1193 bool first = true; 1194 1195 /* 1196 * The "currentPc" is updated whenever we execute an instruction that 1197 * might throw an exception. Show it here. 1198 */ 1199 if (framePtr != NULL && !dvmIsBreakFrame(framePtr)) { 1200 saveArea = SAVEAREA_FROM_FP(framePtr); 1201 1202 if (saveArea->xtra.currentPc != NULL) 1203 currentPc = saveArea->xtra.currentPc; 1204 } 1205 1206 while (framePtr != NULL) { 1207 saveArea = SAVEAREA_FROM_FP(framePtr); 1208 method = saveArea->method; 1209 1210 if (dvmIsBreakFrame(framePtr)) { 1211 //dvmPrintDebugMessage(target, " (break frame)\n"); 1212 } else { 1213 int relPc; 1214 1215 if (currentPc != NULL) 1216 relPc = currentPc - saveArea->method->insns; 1217 else 1218 relPc = -1; 1219 1220 char* className = dvmDescriptorToDot(method->clazz->descriptor); 1221 if (dvmIsNativeMethod(method)) 1222 dvmPrintDebugMessage(target, 1223 " at %s.%s(Native Method)\n", className, method->name); 1224 else { 1225 dvmPrintDebugMessage(target, 1226 " at %s.%s(%s:%s%d)\n", 1227 className, method->name, dvmGetMethodSourceFile(method), 1228 (relPc >= 0 && first) ? "~" : "", 1229 relPc < 0 ? -1 : dvmLineNumFromPC(method, relPc)); 1230 } 1231 free(className); 1232 1233 if (first) { 1234 /* 1235 * Decorate WAIT and MONITOR threads with some detail on 1236 * the first frame. 1237 * 1238 * warning: wait status not stable, even in suspend 1239 */ 1240 if (thread->status == THREAD_WAIT || 1241 thread->status == THREAD_TIMED_WAIT) 1242 { 1243 Monitor* mon = thread->waitMonitor; 1244 Object* obj = dvmGetMonitorObject(mon); 1245 if (obj != NULL) { 1246 className = dvmDescriptorToDot(obj->clazz->descriptor); 1247 dvmPrintDebugMessage(target, 1248 " - waiting on <%p> (a %s)\n", obj, className); 1249 free(className); 1250 } 1251 } else if (thread->status == THREAD_MONITOR) { 1252 Object* obj; 1253 Thread* owner; 1254 if (extractMonitorEnterObject(thread, &obj, &owner)) { 1255 className = dvmDescriptorToDot(obj->clazz->descriptor); 1256 if (owner != NULL) { 1257 char* threadName = dvmGetThreadName(owner); 1258 dvmPrintDebugMessage(target, 1259 " - waiting to lock <%p> (a %s) held by threadid=%d (%s)\n", 1260 obj, className, owner->threadId, threadName); 1261 free(threadName); 1262 } else { 1263 dvmPrintDebugMessage(target, 1264 " - waiting to lock <%p> (a %s) held by ???\n", 1265 obj, className); 1266 } 1267 free(className); 1268 } 1269 } 1270 } 1271 } 1272 1273 /* 1274 * Get saved PC for previous frame. There's no savedPc in a "break" 1275 * frame, because that represents native or interpreted code 1276 * invoked by the VM. The saved PC is sitting in the "PC register", 1277 * a local variable on the native stack. 1278 */ 1279 currentPc = saveArea->savedPc; 1280 1281 first = false; 1282 1283 if (saveArea->prevFrame != NULL && saveArea->prevFrame <= framePtr) { 1284 LOGW("Warning: loop in stack trace at frame %d (%p -> %p)\n", 1285 checkCount, framePtr, saveArea->prevFrame); 1286 break; 1287 } 1288 framePtr = saveArea->prevFrame; 1289 1290 checkCount++; 1291 if (checkCount > 300) { 1292 dvmPrintDebugMessage(target, 1293 " ***** printed %d frames, not showing any more\n", 1294 checkCount); 1295 break; 1296 } 1297 } 1298 dvmPrintDebugMessage(target, "\n"); 1299} 1300 1301 1302/* 1303 * Dump the stack for the specified thread. 1304 */ 1305void dvmDumpThreadStack(const DebugOutputTarget* target, Thread* thread) 1306{ 1307 dumpFrames(target, thread->curFrame, thread); 1308} 1309 1310/* 1311 * Dump the stack for the specified thread, which is still running. 1312 * 1313 * This is very dangerous, because stack frames are being pushed on and 1314 * popped off, and if the thread exits we'll be looking at freed memory. 1315 * The plan here is to take a snapshot of the stack and then dump that 1316 * to try to minimize the chances of catching it mid-update. This should 1317 * work reasonably well on a single-CPU system. 1318 * 1319 * There is a small chance that calling here will crash the VM. 1320 */ 1321void dvmDumpRunningThreadStack(const DebugOutputTarget* target, Thread* thread) 1322{ 1323 StackSaveArea* saveArea; 1324 const u1* origStack; 1325 u1* stackCopy = NULL; 1326 int origSize, fpOffset; 1327 void* fp; 1328 int depthLimit = 200; 1329 1330 if (thread == NULL || thread->curFrame == NULL) { 1331 dvmPrintDebugMessage(target, 1332 "DumpRunning: Thread at %p has no curFrame (threadid=%d)\n", 1333 thread, (thread != NULL) ? thread->threadId : 0); 1334 return; 1335 } 1336 1337 /* wait for a full quantum */ 1338 sched_yield(); 1339 1340 /* copy the info we need, then the stack itself */ 1341 origSize = thread->interpStackSize; 1342 origStack = (const u1*) thread->interpStackStart - origSize; 1343 stackCopy = (u1*) malloc(origSize); 1344 fpOffset = (u1*) thread->curFrame - origStack; 1345 memcpy(stackCopy, origStack, origSize); 1346 1347 /* 1348 * Run through the stack and rewrite the "prev" pointers. 1349 */ 1350 //LOGI("DR: fpOff=%d (from %p %p)\n",fpOffset, origStack, thread->curFrame); 1351 fp = stackCopy + fpOffset; 1352 while (true) { 1353 int prevOffset; 1354 1355 if (depthLimit-- < 0) { 1356 /* we're probably screwed */ 1357 dvmPrintDebugMessage(target, "DumpRunning: depth limit hit\n"); 1358 dvmAbort(); 1359 } 1360 saveArea = SAVEAREA_FROM_FP(fp); 1361 if (saveArea->prevFrame == NULL) 1362 break; 1363 1364 prevOffset = (u1*) saveArea->prevFrame - origStack; 1365 if (prevOffset < 0 || prevOffset > origSize) { 1366 dvmPrintDebugMessage(target, 1367 "DumpRunning: bad offset found: %d (from %p %p)\n", 1368 prevOffset, origStack, saveArea->prevFrame); 1369 saveArea->prevFrame = NULL; 1370 break; 1371 } 1372 1373 saveArea->prevFrame = stackCopy + prevOffset; 1374 fp = saveArea->prevFrame; 1375 } 1376 1377 /* 1378 * We still need to pass the Thread for some monitor wait stuff. 1379 */ 1380 dumpFrames(target, stackCopy + fpOffset, thread); 1381 free(stackCopy); 1382} 1383 1384