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 */ 34 bool 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 */ 59 static 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 */ 134 bool 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 */ 212 bool 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 */ 275 bool 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 */ 309 static 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 */ 359 static 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 */ 429 void 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 */ 447 void 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 533 bail: 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 */ 551 void 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 636 bail: 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 */ 651 Object* 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 776 bail: 777 if (needPop) { 778 dvmPopFrame(self); 779 } 780 return retObj; 781 } 782 783 typedef struct LineNumFromPcContext { 784 u4 address; 785 u4 lineNum; 786 } LineNumFromPcContext; 787 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 */ 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 */ 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 */ 866 int 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 1017 void 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 */ 1066 void 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 */ 1106 static 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 */ 1185 static 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 */ 1304 void 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 */ 1320 void 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