debug.cpp revision 0:a61af66fc99e
1/* 2 * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 20 * CA 95054 USA or visit www.sun.com if you need additional information or 21 * have any questions. 22 * 23 */ 24 25# include "incls/_precompiled.incl" 26# include "incls/_debug.cpp.incl" 27 28#ifndef ASSERT 29# ifdef _DEBUG 30 // NOTE: don't turn the lines below into a comment -- if you're getting 31 // a compile error here, change the settings to define ASSERT 32 ASSERT should be defined when _DEBUG is defined. It is not intended to be used for debugging 33 functions that do not slow down the system too much and thus can be left in optimized code. 34 On the other hand, the code should not be included in a production version. 35# endif // _DEBUG 36#endif // ASSERT 37 38 39#ifdef _DEBUG 40# ifndef ASSERT 41 configuration error: ASSERT must be defined in debug version 42# endif // ASSERT 43#endif // _DEBUG 44 45 46#ifdef PRODUCT 47# if -defined _DEBUG || -defined ASSERT 48 configuration error: ASSERT et al. must not be defined in PRODUCT version 49# endif 50#endif // PRODUCT 51 52 53void warning(const char* format, ...) { 54 // In case error happens before init or during shutdown 55 if (tty == NULL) ostream_init(); 56 57 tty->print("%s warning: ", VM_Version::vm_name()); 58 va_list ap; 59 va_start(ap, format); 60 tty->vprint_cr(format, ap); 61 va_end(ap); 62 if (BreakAtWarning) BREAKPOINT; 63} 64 65#ifndef PRODUCT 66 67#define is_token_break(ch) (isspace(ch) || (ch) == ',') 68 69static const char* last_file_name = NULL; 70static int last_line_no = -1; 71 72// assert/guarantee/... may happen very early during VM initialization. 73// Don't rely on anything that is initialized by Threads::create_vm(). For 74// example, don't use tty. 75bool assert_is_suppressed(const char* file_name, int line_no) { 76 // The following 1-element cache requires that passed-in 77 // file names are always only constant literals. 78 if (file_name == last_file_name && line_no == last_line_no) return true; 79 80 int file_name_len = (int)strlen(file_name); 81 char separator = os::file_separator()[0]; 82 const char* base_name = strrchr(file_name, separator); 83 if (base_name == NULL) 84 base_name = file_name; 85 86 // scan the SuppressErrorAt option 87 const char* cp = SuppressErrorAt; 88 for (;;) { 89 const char* sfile; 90 int sfile_len; 91 int sline; 92 bool noisy; 93 while ((*cp) != '\0' && is_token_break(*cp)) cp++; 94 if ((*cp) == '\0') break; 95 sfile = cp; 96 while ((*cp) != '\0' && !is_token_break(*cp) && (*cp) != ':') cp++; 97 sfile_len = cp - sfile; 98 if ((*cp) == ':') cp++; 99 sline = 0; 100 while ((*cp) != '\0' && isdigit(*cp)) { 101 sline *= 10; 102 sline += (*cp) - '0'; 103 cp++; 104 } 105 // "file:line!" means the assert suppression is not silent 106 noisy = ((*cp) == '!'); 107 while ((*cp) != '\0' && !is_token_break(*cp)) cp++; 108 // match the line 109 if (sline != 0) { 110 if (sline != line_no) continue; 111 } 112 // match the file 113 if (sfile_len > 0) { 114 const char* look = file_name; 115 const char* look_max = file_name + file_name_len - sfile_len; 116 const char* foundp; 117 bool match = false; 118 while (!match 119 && (foundp = strchr(look, sfile[0])) != NULL 120 && foundp <= look_max) { 121 match = true; 122 for (int i = 1; i < sfile_len; i++) { 123 if (sfile[i] != foundp[i]) { 124 match = false; 125 break; 126 } 127 } 128 look = foundp + 1; 129 } 130 if (!match) continue; 131 } 132 // got a match! 133 if (noisy) { 134 fdStream out(defaultStream::output_fd()); 135 out.print_raw("[error suppressed at "); 136 out.print_raw(base_name); 137 char buf[16]; 138 jio_snprintf(buf, sizeof(buf), ":%d]", line_no); 139 out.print_raw_cr(buf); 140 } else { 141 // update 1-element cache for fast silent matches 142 last_file_name = file_name; 143 last_line_no = line_no; 144 } 145 return true; 146 } 147 148 if (!is_error_reported()) { 149 // print a friendly hint: 150 fdStream out(defaultStream::output_fd()); 151 out.print_raw_cr("# To suppress the following error report, specify this argument"); 152 out.print_raw ("# after -XX: or in .hotspotrc: SuppressErrorAt="); 153 out.print_raw (base_name); 154 char buf[16]; 155 jio_snprintf(buf, sizeof(buf), ":%d", line_no); 156 out.print_raw_cr(buf); 157 } 158 return false; 159} 160 161#undef is_token_break 162 163#else 164 165// Place-holder for non-existent suppression check: 166#define assert_is_suppressed(file_name, line_no) (false) 167 168#endif //PRODUCT 169 170void report_assertion_failure(const char* file_name, int line_no, const char* message) { 171 if (Debugging || assert_is_suppressed(file_name, line_no)) return; 172 VMError err(ThreadLocalStorage::get_thread_slow(), message, file_name, line_no); 173 err.report_and_die(); 174} 175 176void report_fatal(const char* file_name, int line_no, const char* message) { 177 if (Debugging || assert_is_suppressed(file_name, line_no)) return; 178 VMError err(ThreadLocalStorage::get_thread_slow(), message, file_name, line_no); 179 err.report_and_die(); 180} 181 182void report_fatal_vararg(const char* file_name, int line_no, const char* format, ...) { 183 char buffer[256]; 184 va_list ap; 185 va_start(ap, format); 186 jio_vsnprintf(buffer, sizeof(buffer), format, ap); 187 va_end(ap); 188 report_fatal(file_name, line_no, buffer); 189} 190 191 192// Used by report_vm_out_of_memory to detect recursion. 193static jint _exiting_out_of_mem = 0; 194 195// Just passing the flow to VMError to handle error 196void report_vm_out_of_memory(const char* file_name, int line_no, size_t size, const char* message) { 197 if (Debugging || assert_is_suppressed(file_name, line_no)) return; 198 199 // We try to gather additional information for the first out of memory 200 // error only; gathering additional data might cause an allocation and a 201 // recursive out_of_memory condition. 202 203 const jint exiting = 1; 204 // If we succeed in changing the value, we're the first one in. 205 bool first_time_here = Atomic::xchg(exiting, &_exiting_out_of_mem) != exiting; 206 207 if (first_time_here) { 208 Thread* thread = ThreadLocalStorage::get_thread_slow(); 209 VMError(thread, size, message, file_name, line_no).report_and_die(); 210 } 211 vm_abort(); 212} 213 214void report_vm_out_of_memory_vararg(const char* file_name, int line_no, size_t size, const char* format, ...) { 215 char buffer[256]; 216 va_list ap; 217 va_start(ap, format); 218 jio_vsnprintf(buffer, sizeof(buffer), format, ap); 219 va_end(ap); 220 report_vm_out_of_memory(file_name, line_no, size, buffer); 221} 222 223void report_should_not_call(const char* file_name, int line_no) { 224 if (Debugging || assert_is_suppressed(file_name, line_no)) return; 225 VMError err(ThreadLocalStorage::get_thread_slow(), "ShouldNotCall()", file_name, line_no); 226 err.report_and_die(); 227} 228 229 230void report_should_not_reach_here(const char* file_name, int line_no) { 231 if (Debugging || assert_is_suppressed(file_name, line_no)) return; 232 VMError err(ThreadLocalStorage::get_thread_slow(), "ShouldNotReachHere()", file_name, line_no); 233 err.report_and_die(); 234} 235 236 237void report_unimplemented(const char* file_name, int line_no) { 238 if (Debugging || assert_is_suppressed(file_name, line_no)) return; 239 VMError err(ThreadLocalStorage::get_thread_slow(), "Unimplemented()", file_name, line_no); 240 err.report_and_die(); 241} 242 243 244void report_untested(const char* file_name, int line_no, const char* msg) { 245#ifndef PRODUCT 246 warning("Untested: %s in %s: %d\n", msg, file_name, line_no); 247#endif // PRODUCT 248} 249 250void report_java_out_of_memory(const char* message) { 251 static jint out_of_memory_reported = 0; 252 253 // A number of threads may attempt to report OutOfMemoryError at around the 254 // same time. To avoid dumping the heap or executing the data collection 255 // commands multiple times we just do it once when the first threads reports 256 // the error. 257 if (Atomic::cmpxchg(1, &out_of_memory_reported, 0) == 0) { 258 // create heap dump before OnOutOfMemoryError commands are executed 259 if (HeapDumpOnOutOfMemoryError) { 260 tty->print_cr("java.lang.OutOfMemoryError: %s", message); 261 HeapDumper::dump_heap(); 262 } 263 264 if (OnOutOfMemoryError && OnOutOfMemoryError[0]) { 265 VMError err(message); 266 err.report_java_out_of_memory(); 267 } 268 } 269} 270 271 272extern "C" void ps(); 273 274static bool error_reported = false; 275 276// call this when the VM is dying--it might loosen some asserts 277void set_error_reported() { 278 error_reported = true; 279} 280 281bool is_error_reported() { 282 return error_reported; 283} 284 285// ------ helper functions for debugging go here ------------ 286 287#ifndef PRODUCT 288// All debug entries should be wrapped with a stack allocated 289// Command object. It makes sure a resource mark is set and 290// flushes the logfile to prevent file sharing problems. 291 292class Command : public StackObj { 293 private: 294 ResourceMark rm; 295 ResetNoHandleMark rnhm; 296 HandleMark hm; 297 bool debug_save; 298 public: 299 static int level; 300 Command(const char* str) { 301 debug_save = Debugging; 302 Debugging = true; 303 if (level++ > 0) return; 304 tty->cr(); 305 tty->print_cr("\"Executing %s\"", str); 306 } 307 308 ~Command() { tty->flush(); Debugging = debug_save; level--; } 309}; 310 311int Command::level = 0; 312 313extern "C" void blob(CodeBlob* cb) { 314 Command c("blob"); 315 cb->print(); 316} 317 318 319extern "C" void dump_vtable(address p) { 320 Command c("dump_vtable"); 321 klassOop k = (klassOop)p; 322 instanceKlass::cast(k)->vtable()->print(); 323} 324 325 326extern "C" void nm(intptr_t p) { 327 // Actually we look through all CodeBlobs (the nm name has been kept for backwards compatability) 328 Command c("nm"); 329 CodeBlob* cb = CodeCache::find_blob((address)p); 330 if (cb == NULL) { 331 tty->print_cr("NULL"); 332 } else { 333 cb->print(); 334 } 335} 336 337 338extern "C" void disnm(intptr_t p) { 339 Command c("disnm"); 340 CodeBlob* cb = CodeCache::find_blob((address) p); 341 cb->print(); 342 Disassembler::decode(cb); 343} 344 345 346extern "C" void printnm(intptr_t p) { 347 char buffer[256]; 348 sprintf(buffer, "printnm: " INTPTR_FORMAT, p); 349 Command c(buffer); 350 CodeBlob* cb = CodeCache::find_blob((address) p); 351 if (cb->is_nmethod()) { 352 nmethod* nm = (nmethod*)cb; 353 nm->print_nmethod(true); 354 } 355} 356 357 358extern "C" void universe() { 359 Command c("universe"); 360 Universe::print(); 361} 362 363 364extern "C" void verify() { 365 // try to run a verify on the entire system 366 // note: this may not be safe if we're not at a safepoint; for debugging, 367 // this manipulates the safepoint settings to avoid assertion failures 368 Command c("universe verify"); 369 bool safe = SafepointSynchronize::is_at_safepoint(); 370 if (!safe) { 371 tty->print_cr("warning: not at safepoint -- verify may fail"); 372 SafepointSynchronize::set_is_at_safepoint(); 373 } 374 // Ensure Eden top is correct before verification 375 Universe::heap()->prepare_for_verify(); 376 Universe::verify(true); 377 if (!safe) SafepointSynchronize::set_is_not_at_safepoint(); 378} 379 380 381extern "C" void pp(void* p) { 382 Command c("pp"); 383 FlagSetting fl(PrintVMMessages, true); 384 if (Universe::heap()->is_in(p)) { 385 oop obj = oop(p); 386 obj->print(); 387 } else { 388 tty->print("%#p", p); 389 } 390} 391 392 393// pv: print vm-printable object 394extern "C" void pa(intptr_t p) { ((AllocatedObj*) p)->print(); } 395extern "C" void findpc(intptr_t x); 396 397extern "C" void ps() { // print stack 398 Command c("ps"); 399 400 401 // Prints the stack of the current Java thread 402 JavaThread* p = JavaThread::active(); 403 tty->print(" for thread: "); 404 p->print(); 405 tty->cr(); 406 407 if (p->has_last_Java_frame()) { 408 // If the last_Java_fp is set we are in C land and 409 // can call the standard stack_trace function. 410 p->trace_stack(); 411 } else { 412 frame f = os::current_frame(); 413 RegisterMap reg_map(p); 414 f = f.sender(®_map); 415 tty->print("(guessing starting frame id=%#p based on current fp)\n", f.id()); 416 p->trace_stack_from(vframe::new_vframe(&f, ®_map, p)); 417 pd_ps(f); 418 } 419 420} 421 422 423extern "C" void psf() { // print stack frames 424 { 425 Command c("psf"); 426 JavaThread* p = JavaThread::active(); 427 tty->print(" for thread: "); 428 p->print(); 429 tty->cr(); 430 if (p->has_last_Java_frame()) { 431 p->trace_frames(); 432 } 433 } 434} 435 436 437extern "C" void threads() { 438 Command c("threads"); 439 Threads::print(false, true); 440} 441 442 443extern "C" void psd() { 444 Command c("psd"); 445 SystemDictionary::print(); 446} 447 448 449extern "C" void safepoints() { 450 Command c("safepoints"); 451 SafepointSynchronize::print_state(); 452} 453 454 455extern "C" void pss() { // print all stacks 456 Command c("pss"); 457 Threads::print(true, true); 458} 459 460 461extern "C" void debug() { // to set things up for compiler debugging 462 Command c("debug"); 463 WizardMode = true; 464 PrintVMMessages = PrintCompilation = true; 465 PrintInlining = PrintAssembly = true; 466 tty->flush(); 467} 468 469 470extern "C" void ndebug() { // undo debug() 471 Command c("ndebug"); 472 PrintCompilation = false; 473 PrintInlining = PrintAssembly = false; 474 tty->flush(); 475} 476 477 478extern "C" void flush() { 479 Command c("flush"); 480 tty->flush(); 481} 482 483 484extern "C" void events() { 485 Command c("events"); 486 Events::print_last(tty, 50); 487} 488 489 490extern "C" void nevents(int n) { 491 Command c("events"); 492 Events::print_last(tty, n); 493} 494 495 496// Given a heap address that was valid before the most recent GC, if 497// the oop that used to contain it is still live, prints the new 498// location of the oop and the address. Useful for tracking down 499// certain kinds of naked oop and oop map bugs. 500extern "C" void pnl(intptr_t old_heap_addr) { 501 // Print New Location of old heap address 502 Command c("pnl"); 503#ifndef VALIDATE_MARK_SWEEP 504 tty->print_cr("Requires build with VALIDATE_MARK_SWEEP defined (debug build) and RecordMarkSweepCompaction enabled"); 505#else 506 MarkSweep::print_new_location_of_heap_address((HeapWord*) old_heap_addr); 507#endif 508} 509 510 511extern "C" methodOop findm(intptr_t pc) { 512 Command c("findm"); 513 nmethod* nm = CodeCache::find_nmethod((address)pc); 514 return (nm == NULL) ? (methodOop)NULL : nm->method(); 515} 516 517 518extern "C" nmethod* findnm(intptr_t addr) { 519 Command c("findnm"); 520 return CodeCache::find_nmethod((address)addr); 521} 522 523static address same_page(address x, address y) { 524 intptr_t page_bits = -os::vm_page_size(); 525 if ((intptr_t(x) & page_bits) == (intptr_t(y) & page_bits)) { 526 return x; 527 } else if (x > y) { 528 return (address)(intptr_t(y) | ~page_bits) + 1; 529 } else { 530 return (address)(intptr_t(y) & page_bits); 531 } 532} 533 534 535static void find(intptr_t x, bool print_pc) { 536 address addr = (address)x; 537 538 CodeBlob* b = CodeCache::find_blob_unsafe(addr); 539 if (b != NULL) { 540 if (b->is_buffer_blob()) { 541 // the interpreter is generated into a buffer blob 542 InterpreterCodelet* i = Interpreter::codelet_containing(addr); 543 if (i != NULL) { 544 i->print(); 545 return; 546 } 547 if (Interpreter::contains(addr)) { 548 tty->print_cr(INTPTR_FORMAT " is pointing into interpreter code (not bytecode specific)", addr); 549 return; 550 } 551 // 552 if (AdapterHandlerLibrary::contains(b)) { 553 AdapterHandlerLibrary::print_handler(b); 554 } 555 // the stubroutines are generated into a buffer blob 556 StubCodeDesc* d = StubCodeDesc::desc_for(addr); 557 if (d != NULL) { 558 d->print(); 559 if (print_pc) tty->cr(); 560 return; 561 } 562 if (StubRoutines::contains(addr)) { 563 tty->print_cr(INTPTR_FORMAT " is pointing to an (unnamed) stub routine", addr); 564 return; 565 } 566 // the InlineCacheBuffer is using stubs generated into a buffer blob 567 if (InlineCacheBuffer::contains(addr)) { 568 tty->print_cr(INTPTR_FORMAT "is pointing into InlineCacheBuffer", addr); 569 return; 570 } 571 VtableStub* v = VtableStubs::stub_containing(addr); 572 if (v != NULL) { 573 v->print(); 574 return; 575 } 576 } 577 if (print_pc && b->is_nmethod()) { 578 ResourceMark rm; 579 tty->print("%#p: Compiled ", addr); 580 ((nmethod*)b)->method()->print_value_on(tty); 581 tty->print(" = (CodeBlob*)" INTPTR_FORMAT, b); 582 tty->cr(); 583 return; 584 } 585 if ( b->is_nmethod()) { 586 if (b->is_zombie()) { 587 tty->print_cr(INTPTR_FORMAT " is zombie nmethod", b); 588 } else if (b->is_not_entrant()) { 589 tty->print_cr(INTPTR_FORMAT " is non-entrant nmethod", b); 590 } 591 } 592 b->print(); 593 return; 594 } 595 596 if (Universe::heap()->is_in_reserved(addr)) { 597 HeapWord* p = Universe::heap()->block_start(addr); 598 bool print = false; 599 // If we couldn't find it it just may mean that heap wasn't parseable 600 // See if we were just given an oop directly 601 if (p != NULL && Universe::heap()->block_is_obj(p)) { 602 print = true; 603 } else if (p == NULL && ((oopDesc*)addr)->is_oop()) { 604 p = (HeapWord*) addr; 605 print = true; 606 } 607 if (print) { 608 oop(p)->print(); 609 if (p != (HeapWord*)x && oop(p)->is_constMethod() && 610 constMethodOop(p)->contains(addr)) { 611 Thread *thread = Thread::current(); 612 HandleMark hm(thread); 613 methodHandle mh (thread, constMethodOop(p)->method()); 614 if (!mh->is_native()) { 615 tty->print_cr("bci_from(%p) = %d; print_codes():", 616 addr, mh->bci_from(address(x))); 617 mh->print_codes(); 618 } 619 } 620 return; 621 } 622 } 623 if (JNIHandles::is_global_handle((jobject) addr)) { 624 tty->print_cr(INTPTR_FORMAT "is a global jni handle", addr); 625 return; 626 } 627 if (JNIHandles::is_weak_global_handle((jobject) addr)) { 628 tty->print_cr(INTPTR_FORMAT "is a weak global jni handle", addr); 629 return; 630 } 631 if (JNIHandleBlock::any_contains((jobject) addr)) { 632 tty->print_cr(INTPTR_FORMAT "is a local jni handle", addr); 633 return; 634 } 635 636 for(JavaThread *thread = Threads::first(); thread; thread = thread->next()) { 637 // Check for priviledge stack 638 if (thread->privileged_stack_top() != NULL && thread->privileged_stack_top()->contains(addr)) { 639 tty->print_cr(INTPTR_FORMAT "is pointing into the priviledge stack for thread: " INTPTR_FORMAT, addr, thread); 640 return; 641 } 642 // If the addr is a java thread print information about that. 643 if (addr == (address)thread) { 644 thread->print(); 645 return; 646 } 647 } 648 649 // Try an OS specific find 650 if (os::find(addr)) { 651 return; 652 } 653 654 if (print_pc) { 655 tty->print_cr(INTPTR_FORMAT ": probably in C++ code; check debugger", addr); 656 Disassembler::decode(same_page(addr-40,addr),same_page(addr+40,addr)); 657 return; 658 } 659 660 tty->print_cr(INTPTR_FORMAT "is pointing to unknown location", addr); 661} 662 663 664class LookForRefInGenClosure : public OopsInGenClosure { 665public: 666 oop target; 667 void do_oop(oop* o) { 668 if (o != NULL && *o == target) { 669 tty->print_cr("0x%08x", o); 670 } 671 } 672}; 673 674 675class LookForRefInObjectClosure : public ObjectClosure { 676private: 677 LookForRefInGenClosure look_in_object; 678public: 679 LookForRefInObjectClosure(oop target) { look_in_object.target = target; } 680 void do_object(oop obj) { 681 obj->oop_iterate(&look_in_object); 682 } 683}; 684 685 686static void findref(intptr_t x) { 687 GenCollectedHeap *gch = GenCollectedHeap::heap(); 688 LookForRefInGenClosure lookFor; 689 lookFor.target = (oop) x; 690 LookForRefInObjectClosure look_in_object((oop) x); 691 692 tty->print_cr("Searching heap:"); 693 gch->object_iterate(&look_in_object); 694 695 tty->print_cr("Searching strong roots:"); 696 Universe::oops_do(&lookFor, false); 697 JNIHandles::oops_do(&lookFor); // Global (strong) JNI handles 698 Threads::oops_do(&lookFor); 699 ObjectSynchronizer::oops_do(&lookFor); 700 //FlatProfiler::oops_do(&lookFor); 701 SystemDictionary::oops_do(&lookFor); 702 703 tty->print_cr("Done."); 704} 705 706class FindClassObjectClosure: public ObjectClosure { 707 private: 708 const char* _target; 709 public: 710 FindClassObjectClosure(const char name[]) { _target = name; } 711 712 virtual void do_object(oop obj) { 713 if (obj->is_klass()) { 714 Klass* k = klassOop(obj)->klass_part(); 715 if (k->name() != NULL) { 716 ResourceMark rm; 717 const char* ext = k->external_name(); 718 if ( strcmp(_target, ext) == 0 ) { 719 tty->print_cr("Found " INTPTR_FORMAT, obj); 720 obj->print(); 721 } 722 } 723 } 724 } 725}; 726 727// 728extern "C" void findclass(const char name[]) { 729 Command c("findclass"); 730 if (name != NULL) { 731 tty->print_cr("Finding class %s -> ", name); 732 FindClassObjectClosure srch(name); 733 Universe::heap()->permanent_object_iterate(&srch); 734 } 735} 736 737// Another interface that isn't ambiguous in dbx. 738// Can we someday rename the other find to hsfind? 739extern "C" void hsfind(intptr_t x) { 740 Command c("hsfind"); 741 find(x, false); 742} 743 744 745extern "C" void hsfindref(intptr_t x) { 746 Command c("hsfindref"); 747 findref(x); 748} 749 750extern "C" void find(intptr_t x) { 751 Command c("find"); 752 find(x, false); 753} 754 755 756extern "C" void findpc(intptr_t x) { 757 Command c("findpc"); 758 find(x, true); 759} 760 761 762// int versions of all methods to avoid having to type type casts in the debugger 763 764void pp(intptr_t p) { pp((void*)p); } 765void pp(oop p) { pp((void*)p); } 766 767void help() { 768 Command c("help"); 769 tty->print_cr("basic"); 770 tty->print_cr(" pp(void* p) - try to make sense of p"); 771 tty->print_cr(" pv(intptr_t p)- ((PrintableResourceObj*) p)->print()"); 772 tty->print_cr(" ps() - print current thread stack"); 773 tty->print_cr(" pss() - print all thread stacks"); 774 tty->print_cr(" pm(int pc) - print methodOop given compiled PC"); 775 tty->print_cr(" findm(intptr_t pc) - finds methodOop"); 776 tty->print_cr(" find(intptr_t x) - finds & prints nmethod/stub/bytecode/oop based on pointer into it"); 777 778 tty->print_cr("misc."); 779 tty->print_cr(" flush() - flushes the log file"); 780 tty->print_cr(" events() - dump last 50 events"); 781 782 783 tty->print_cr("compiler debugging"); 784 tty->print_cr(" debug() - to set things up for compiler debugging"); 785 tty->print_cr(" ndebug() - undo debug"); 786} 787 788#if 0 789 790// BobV's command parser for debugging on windows when nothing else works. 791 792enum CommandID { 793 CMDID_HELP, 794 CMDID_QUIT, 795 CMDID_HSFIND, 796 CMDID_PSS, 797 CMDID_PS, 798 CMDID_PSF, 799 CMDID_FINDM, 800 CMDID_FINDNM, 801 CMDID_PP, 802 CMDID_BPT, 803 CMDID_EXIT, 804 CMDID_VERIFY, 805 CMDID_THREADS, 806 CMDID_ILLEGAL = 99 807}; 808 809struct CommandParser { 810 char *name; 811 CommandID code; 812 char *description; 813}; 814 815struct CommandParser CommandList[] = { 816 (char *)"help", CMDID_HELP, " Dump this list", 817 (char *)"quit", CMDID_QUIT, " Return from this routine", 818 (char *)"hsfind", CMDID_HSFIND, "Perform an hsfind on an address", 819 (char *)"ps", CMDID_PS, " Print Current Thread Stack Trace", 820 (char *)"pss", CMDID_PSS, " Print All Thread Stack Trace", 821 (char *)"psf", CMDID_PSF, " Print All Stack Frames", 822 (char *)"findm", CMDID_FINDM, " Find a methodOop from a PC", 823 (char *)"findnm", CMDID_FINDNM, "Find an nmethod from a PC", 824 (char *)"pp", CMDID_PP, " Find out something about a pointer", 825 (char *)"break", CMDID_BPT, " Execute a breakpoint", 826 (char *)"exitvm", CMDID_EXIT, "Exit the VM", 827 (char *)"verify", CMDID_VERIFY, "Perform a Heap Verify", 828 (char *)"thread", CMDID_THREADS, "Dump Info on all Threads", 829 (char *)0, CMDID_ILLEGAL 830}; 831 832 833// get_debug_command() 834// 835// Read a command from standard input. 836// This is useful when you have a debugger 837// which doesn't support calling into functions. 838// 839void get_debug_command() 840{ 841 ssize_t count; 842 int i,j; 843 bool gotcommand; 844 intptr_t addr; 845 char buffer[256]; 846 nmethod *nm; 847 methodOop m; 848 849 tty->print_cr("You have entered the diagnostic command interpreter"); 850 tty->print("The supported commands are:\n"); 851 for ( i=0; ; i++ ) { 852 if ( CommandList[i].code == CMDID_ILLEGAL ) 853 break; 854 tty->print_cr(" %s \n", CommandList[i].name ); 855 } 856 857 while ( 1 ) { 858 gotcommand = false; 859 tty->print("Please enter a command: "); 860 count = scanf("%s", buffer) ; 861 if ( count >=0 ) { 862 for ( i=0; ; i++ ) { 863 if ( CommandList[i].code == CMDID_ILLEGAL ) { 864 if (!gotcommand) tty->print("Invalid command, please try again\n"); 865 break; 866 } 867 if ( strcmp(buffer, CommandList[i].name) == 0 ) { 868 gotcommand = true; 869 switch ( CommandList[i].code ) { 870 case CMDID_PS: 871 ps(); 872 break; 873 case CMDID_PSS: 874 pss(); 875 break; 876 case CMDID_PSF: 877 psf(); 878 break; 879 case CMDID_FINDM: 880 tty->print("Please enter the hex addr to pass to findm: "); 881 scanf("%I64X", &addr); 882 m = (methodOop)findm(addr); 883 tty->print("findm(0x%I64X) returned 0x%I64X\n", addr, m); 884 break; 885 case CMDID_FINDNM: 886 tty->print("Please enter the hex addr to pass to findnm: "); 887 scanf("%I64X", &addr); 888 nm = (nmethod*)findnm(addr); 889 tty->print("findnm(0x%I64X) returned 0x%I64X\n", addr, nm); 890 break; 891 case CMDID_PP: 892 tty->print("Please enter the hex addr to pass to pp: "); 893 scanf("%I64X", &addr); 894 pp((void*)addr); 895 break; 896 case CMDID_EXIT: 897 exit(0); 898 case CMDID_HELP: 899 tty->print("Here are the supported commands: "); 900 for ( j=0; ; j++ ) { 901 if ( CommandList[j].code == CMDID_ILLEGAL ) 902 break; 903 tty->print_cr(" %s -- %s\n", CommandList[j].name, 904 CommandList[j].description ); 905 } 906 break; 907 case CMDID_QUIT: 908 return; 909 break; 910 case CMDID_BPT: 911 BREAKPOINT; 912 break; 913 case CMDID_VERIFY: 914 verify();; 915 break; 916 case CMDID_THREADS: 917 threads();; 918 break; 919 case CMDID_HSFIND: 920 tty->print("Please enter the hex addr to pass to hsfind: "); 921 scanf("%I64X", &addr); 922 tty->print("Calling hsfind(0x%I64X)\n", addr); 923 hsfind(addr); 924 break; 925 default: 926 case CMDID_ILLEGAL: 927 break; 928 } 929 } 930 } 931 } 932 } 933} 934#endif 935 936#endif // PRODUCT 937