1 /* 2 * Copyright (c) 1997, 2010, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * 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 53 void warning(const char* format, ...) { 54 if (PrintWarnings) { 55 // In case error happens before init or during shutdown 56 if (tty == NULL) ostream_init(); 57 58 tty->print("%s warning: ", VM_Version::vm_name()); 59 va_list ap; 60 va_start(ap, format); 61 tty->vprint_cr(format, ap); 62 va_end(ap); 63 } 64 if (BreakAtWarning) BREAKPOINT; 65 } 66 67 #ifndef PRODUCT 68 69 #define is_token_break(ch) (isspace(ch) || (ch) == ',') 70 71 static const char* last_file_name = NULL; 72 static int last_line_no = -1; 73 74 // assert/guarantee/... may happen very early during VM initialization. 75 // Don't rely on anything that is initialized by Threads::create_vm(). For 76 // example, don't use tty. 77 bool error_is_suppressed(const char* file_name, int line_no) { 78 // The following 1-element cache requires that passed-in 79 // file names are always only constant literals. 80 if (file_name == last_file_name && line_no == last_line_no) return true; 81 82 int file_name_len = (int)strlen(file_name); 83 char separator = os::file_separator()[0]; 84 const char* base_name = strrchr(file_name, separator); 85 if (base_name == NULL) 86 base_name = file_name; 87 88 // scan the SuppressErrorAt option 89 const char* cp = SuppressErrorAt; 90 for (;;) { 91 const char* sfile; 92 int sfile_len; 93 int sline; 94 bool noisy; 95 while ((*cp) != '\0' && is_token_break(*cp)) cp++; 96 if ((*cp) == '\0') break; 97 sfile = cp; 98 while ((*cp) != '\0' && !is_token_break(*cp) && (*cp) != ':') cp++; 99 sfile_len = cp - sfile; 100 if ((*cp) == ':') cp++; 101 sline = 0; 102 while ((*cp) != '\0' && isdigit(*cp)) { 103 sline *= 10; 104 sline += (*cp) - '0'; 105 cp++; 106 } 107 // "file:line!" means the assert suppression is not silent 108 noisy = ((*cp) == '!'); 109 while ((*cp) != '\0' && !is_token_break(*cp)) cp++; 110 // match the line 111 if (sline != 0) { 112 if (sline != line_no) continue; 113 } 114 // match the file 115 if (sfile_len > 0) { 116 const char* look = file_name; 117 const char* look_max = file_name + file_name_len - sfile_len; 118 const char* foundp; 119 bool match = false; 120 while (!match 121 && (foundp = strchr(look, sfile[0])) != NULL 122 && foundp <= look_max) { 123 match = true; 124 for (int i = 1; i < sfile_len; i++) { 125 if (sfile[i] != foundp[i]) { 126 match = false; 127 break; 128 } 129 } 130 look = foundp + 1; 131 } 132 if (!match) continue; 133 } 134 // got a match! 135 if (noisy) { 136 fdStream out(defaultStream::output_fd()); 137 out.print_raw("[error suppressed at "); 138 out.print_raw(base_name); 139 char buf[16]; 140 jio_snprintf(buf, sizeof(buf), ":%d]", line_no); 141 out.print_raw_cr(buf); 142 } else { 143 // update 1-element cache for fast silent matches 144 last_file_name = file_name; 145 last_line_no = line_no; 146 } 147 return true; 148 } 149 150 if (!is_error_reported()) { 151 // print a friendly hint: 152 fdStream out(defaultStream::output_fd()); 153 out.print_raw_cr("# To suppress the following error report, specify this argument"); 154 out.print_raw ("# after -XX: or in .hotspotrc: SuppressErrorAt="); 155 out.print_raw (base_name); 156 char buf[16]; 157 jio_snprintf(buf, sizeof(buf), ":%d", line_no); 158 out.print_raw_cr(buf); 159 } 160 return false; 161 } 162 163 #undef is_token_break 164 165 #else 166 167 // Place-holder for non-existent suppression check: 168 #define error_is_suppressed(file_name, line_no) (false) 169 170 #endif //PRODUCT 171 172 void report_vm_error(const char* file, int line, const char* error_msg, 173 const char* detail_msg) 174 { 175 if (Debugging || error_is_suppressed(file, line)) return; 176 Thread* const thread = ThreadLocalStorage::get_thread_slow(); 177 VMError err(thread, file, line, error_msg, detail_msg); 178 err.report_and_die(); 179 } 180 181 void report_fatal(const char* file, int line, const char* message) 182 { 183 report_vm_error(file, line, "fatal error", message); 184 } 185 186 // Used by report_vm_out_of_memory to detect recursion. 187 static jint _exiting_out_of_mem = 0; 188 189 void report_vm_out_of_memory(const char* file, int line, size_t size, 190 const char* message) { 191 if (Debugging || error_is_suppressed(file, line)) return; 192 193 // We try to gather additional information for the first out of memory 194 // error only; gathering additional data might cause an allocation and a 195 // recursive out_of_memory condition. 196 197 const jint exiting = 1; 198 // If we succeed in changing the value, we're the first one in. 199 bool first_time_here = Atomic::xchg(exiting, &_exiting_out_of_mem) != exiting; 200 201 if (first_time_here) { 202 Thread* thread = ThreadLocalStorage::get_thread_slow(); 203 VMError(thread, file, line, size, message).report_and_die(); 204 } 205 206 // Dump core and abort 207 vm_abort(true); 208 } 209 210 void report_should_not_call(const char* file, int line) { 211 report_vm_error(file, line, "ShouldNotCall()"); 212 } 213 214 void report_should_not_reach_here(const char* file, int line) { 215 report_vm_error(file, line, "ShouldNotReachHere()"); 216 } 217 218 void report_unimplemented(const char* file, int line) { 219 report_vm_error(file, line, "Unimplemented()"); 220 } 221 222 void report_untested(const char* file, int line, const char* message) { 223 #ifndef PRODUCT 224 warning("Untested: %s in %s: %d\n", message, file, line); 225 #endif // PRODUCT 226 } 227 228 void report_java_out_of_memory(const char* message) { 229 static jint out_of_memory_reported = 0; 230 231 // A number of threads may attempt to report OutOfMemoryError at around the 232 // same time. To avoid dumping the heap or executing the data collection 233 // commands multiple times we just do it once when the first threads reports 234 // the error. 235 if (Atomic::cmpxchg(1, &out_of_memory_reported, 0) == 0) { 236 // create heap dump before OnOutOfMemoryError commands are executed 237 if (HeapDumpOnOutOfMemoryError) { 238 tty->print_cr("java.lang.OutOfMemoryError: %s", message); 239 HeapDumper::dump_heap_from_oome(); 240 } 241 242 if (OnOutOfMemoryError && OnOutOfMemoryError[0]) { 243 VMError err(message); 244 err.report_java_out_of_memory(); 245 } 246 } 247 } 248 249 250 extern "C" void ps(); 251 252 static bool error_reported = false; 253 254 // call this when the VM is dying--it might loosen some asserts 255 void set_error_reported() { 256 error_reported = true; 257 } 258 259 bool is_error_reported() { 260 return error_reported; 261 } 262 263 #ifndef PRODUCT 264 #include <signal.h> 265 266 void test_error_handler(size_t test_num) 267 { 268 if (test_num == 0) return; 269 270 // If asserts are disabled, use the corresponding guarantee instead. 271 size_t n = test_num; 272 NOT_DEBUG(if (n <= 2) n += 2); 273 274 const char* const str = "hello"; 275 const size_t num = (size_t)os::vm_page_size(); 276 277 const char* const eol = os::line_separator(); 278 const char* const msg = "this message should be truncated during formatting"; 279 280 // Keep this in sync with test/runtime/6888954/vmerrors.sh. 281 switch (n) { 282 case 1: assert(str == NULL, "expected null"); 283 case 2: assert(num == 1023 && *str == 'X', 284 err_msg("num=" SIZE_FORMAT " str=\"%s\"", num, str)); 285 case 3: guarantee(str == NULL, "expected null"); 286 case 4: guarantee(num == 1023 && *str == 'X', 287 err_msg("num=" SIZE_FORMAT " str=\"%s\"", num, str)); 288 case 5: fatal("expected null"); 289 case 6: fatal(err_msg("num=" SIZE_FORMAT " str=\"%s\"", num, str)); 290 case 7: fatal(err_msg("%s%s# %s%s# %s%s# %s%s# %s%s# " 291 "%s%s# %s%s# %s%s# %s%s# %s%s# " 292 "%s%s# %s%s# %s%s# %s%s# %s", 293 msg, eol, msg, eol, msg, eol, msg, eol, msg, eol, 294 msg, eol, msg, eol, msg, eol, msg, eol, msg, eol, 295 msg, eol, msg, eol, msg, eol, msg, eol, msg)); 296 case 8: vm_exit_out_of_memory(num, "ChunkPool::allocate"); 297 case 9: ShouldNotCallThis(); 298 case 10: ShouldNotReachHere(); 299 case 11: Unimplemented(); 300 // This is last because it does not generate an hs_err* file on Windows. 301 case 12: os::signal_raise(SIGSEGV); 302 303 default: ShouldNotReachHere(); 304 } 305 } 306 #endif // #ifndef PRODUCT 307 308 // ------ helper functions for debugging go here ------------ 309 310 #ifndef PRODUCT 311 // All debug entries should be wrapped with a stack allocated 312 // Command object. It makes sure a resource mark is set and 313 // flushes the logfile to prevent file sharing problems. 314 315 class Command : public StackObj { 316 private: 317 ResourceMark rm; 318 ResetNoHandleMark rnhm; 319 HandleMark hm; 320 bool debug_save; 321 public: 322 static int level; 323 Command(const char* str) { 324 debug_save = Debugging; 325 Debugging = true; 326 if (level++ > 0) return; 327 tty->cr(); 328 tty->print_cr("\"Executing %s\"", str); 329 } 330 331 ~Command() { tty->flush(); Debugging = debug_save; level--; } 332 }; 333 334 int Command::level = 0; 335 336 extern "C" void blob(CodeBlob* cb) { 337 Command c("blob"); 338 cb->print(); 339 } 340 341 342 extern "C" void dump_vtable(address p) { 343 Command c("dump_vtable"); 344 klassOop k = (klassOop)p; 345 instanceKlass::cast(k)->vtable()->print(); 346 } 347 348 349 extern "C" void nm(intptr_t p) { 350 // Actually we look through all CodeBlobs (the nm name has been kept for backwards compatability) 351 Command c("nm"); 352 CodeBlob* cb = CodeCache::find_blob((address)p); 353 if (cb == NULL) { 354 tty->print_cr("NULL"); 355 } else { 356 cb->print(); 357 } 358 } 359 360 361 extern "C" void disnm(intptr_t p) { 362 Command c("disnm"); 363 CodeBlob* cb = CodeCache::find_blob((address) p); 364 nmethod* nm = cb->as_nmethod_or_null(); 365 if (nm) { 366 nm->print(); 367 Disassembler::decode(nm); 368 } else { 369 cb->print(); 370 Disassembler::decode(cb); 371 } 372 } 373 374 375 extern "C" void printnm(intptr_t p) { 376 char buffer[256]; 377 sprintf(buffer, "printnm: " INTPTR_FORMAT, p); 378 Command c(buffer); 379 CodeBlob* cb = CodeCache::find_blob((address) p); 380 if (cb->is_nmethod()) { 381 nmethod* nm = (nmethod*)cb; 382 nm->print_nmethod(true); 383 } 384 } 385 386 387 extern "C" void universe() { 388 Command c("universe"); 389 Universe::print(); 390 } 391 392 393 extern "C" void verify() { 394 // try to run a verify on the entire system 395 // note: this may not be safe if we're not at a safepoint; for debugging, 396 // this manipulates the safepoint settings to avoid assertion failures 397 Command c("universe verify"); 398 bool safe = SafepointSynchronize::is_at_safepoint(); 399 if (!safe) { 400 tty->print_cr("warning: not at safepoint -- verify may fail"); 401 SafepointSynchronize::set_is_at_safepoint(); 402 } 403 // Ensure Eden top is correct before verification 404 Universe::heap()->prepare_for_verify(); 405 Universe::verify(true); 406 if (!safe) SafepointSynchronize::set_is_not_at_safepoint(); 407 } 408 409 410 extern "C" void pp(void* p) { 411 Command c("pp"); 412 FlagSetting fl(PrintVMMessages, true); 413 if (Universe::heap()->is_in(p)) { 414 oop obj = oop(p); 415 obj->print(); 416 } else { 417 tty->print("%#p", p); 418 } 419 } 420 421 422 // pv: print vm-printable object 423 extern "C" void pa(intptr_t p) { ((AllocatedObj*) p)->print(); } 424 extern "C" void findpc(intptr_t x); 425 426 extern "C" void ps() { // print stack 427 Command c("ps"); 428 429 430 // Prints the stack of the current Java thread 431 JavaThread* p = JavaThread::active(); 432 tty->print(" for thread: "); 433 p->print(); 434 tty->cr(); 435 436 if (p->has_last_Java_frame()) { 437 // If the last_Java_fp is set we are in C land and 438 // can call the standard stack_trace function. 439 p->trace_stack(); 440 } else { 441 frame f = os::current_frame(); 442 RegisterMap reg_map(p); 443 f = f.sender(®_map); 444 tty->print("(guessing starting frame id=%#p based on current fp)\n", f.id()); 445 p->trace_stack_from(vframe::new_vframe(&f, ®_map, p)); 446 pd_ps(f); 447 } 448 449 } 450 451 452 extern "C" void psf() { // print stack frames 453 { 454 Command c("psf"); 455 JavaThread* p = JavaThread::active(); 456 tty->print(" for thread: "); 457 p->print(); 458 tty->cr(); 459 if (p->has_last_Java_frame()) { 460 p->trace_frames(); 461 } 462 } 463 } 464 465 466 extern "C" void threads() { 467 Command c("threads"); 468 Threads::print(false, true); 469 } 470 471 472 extern "C" void psd() { 473 Command c("psd"); 474 SystemDictionary::print(); 475 } 476 477 478 extern "C" void safepoints() { 479 Command c("safepoints"); 480 SafepointSynchronize::print_state(); 481 } 482 483 484 extern "C" void pss() { // print all stacks 485 Command c("pss"); 486 Threads::print(true, true); 487 } 488 489 490 extern "C" void debug() { // to set things up for compiler debugging 491 Command c("debug"); 492 WizardMode = true; 493 PrintVMMessages = PrintCompilation = true; 494 PrintInlining = PrintAssembly = true; 495 tty->flush(); 496 } 497 498 499 extern "C" void ndebug() { // undo debug() 500 Command c("ndebug"); 501 PrintCompilation = false; 502 PrintInlining = PrintAssembly = false; 503 tty->flush(); 504 } 505 506 507 extern "C" void flush() { 508 Command c("flush"); 509 tty->flush(); 510 } 511 512 513 extern "C" void events() { 514 Command c("events"); 515 Events::print_last(tty, 50); 516 } 517 518 519 extern "C" void nevents(int n) { 520 Command c("events"); 521 Events::print_last(tty, n); 522 } 523 524 525 // Given a heap address that was valid before the most recent GC, if 526 // the oop that used to contain it is still live, prints the new 527 // location of the oop and the address. Useful for tracking down 528 // certain kinds of naked oop and oop map bugs. 529 extern "C" void pnl(intptr_t old_heap_addr) { 530 // Print New Location of old heap address 531 Command c("pnl"); 532 #ifndef VALIDATE_MARK_SWEEP 533 tty->print_cr("Requires build with VALIDATE_MARK_SWEEP defined (debug build) and RecordMarkSweepCompaction enabled"); 534 #else 535 MarkSweep::print_new_location_of_heap_address((HeapWord*) old_heap_addr); 536 #endif 537 } 538 539 540 extern "C" methodOop findm(intptr_t pc) { 541 Command c("findm"); 542 nmethod* nm = CodeCache::find_nmethod((address)pc); 543 return (nm == NULL) ? (methodOop)NULL : nm->method(); 544 } 545 546 547 extern "C" nmethod* findnm(intptr_t addr) { 548 Command c("findnm"); 549 return CodeCache::find_nmethod((address)addr); 550 } 551 552 static address same_page(address x, address y) { 553 intptr_t page_bits = -os::vm_page_size(); 554 if ((intptr_t(x) & page_bits) == (intptr_t(y) & page_bits)) { 555 return x; 556 } else if (x > y) { 557 return (address)(intptr_t(y) | ~page_bits) + 1; 558 } else { 559 return (address)(intptr_t(y) & page_bits); 560 } 561 } 562 563 class LookForRefInGenClosure : public OopsInGenClosure { 564 public: 565 oop target; 566 void do_oop(oop* o) { 567 if (o != NULL && *o == target) { 568 tty->print_cr(INTPTR_FORMAT, o); 569 } 570 } 571 void do_oop(narrowOop* o) { ShouldNotReachHere(); } 572 }; 573 574 575 class LookForRefInObjectClosure : public ObjectClosure { 576 private: 577 LookForRefInGenClosure look_in_object; 578 public: 579 LookForRefInObjectClosure(oop target) { look_in_object.target = target; } 580 void do_object(oop obj) { 581 obj->oop_iterate(&look_in_object); 582 } 583 }; 584 585 586 static void findref(intptr_t x) { 587 CollectedHeap *ch = Universe::heap(); 588 LookForRefInGenClosure lookFor; 589 lookFor.target = (oop) x; 590 LookForRefInObjectClosure look_in_object((oop) x); 591 592 tty->print_cr("Searching heap:"); 593 ch->object_iterate(&look_in_object); 594 595 tty->print_cr("Searching strong roots:"); 596 Universe::oops_do(&lookFor, false); 597 JNIHandles::oops_do(&lookFor); // Global (strong) JNI handles 598 Threads::oops_do(&lookFor, NULL); 599 ObjectSynchronizer::oops_do(&lookFor); 600 //FlatProfiler::oops_do(&lookFor); 601 SystemDictionary::oops_do(&lookFor); 602 603 tty->print_cr("Searching code cache:"); 604 CodeCache::oops_do(&lookFor); 605 606 tty->print_cr("Done."); 607 } 608 609 class FindClassObjectClosure: public ObjectClosure { 610 private: 611 const char* _target; 612 public: 613 FindClassObjectClosure(const char name[]) { _target = name; } 614 615 virtual void do_object(oop obj) { 616 if (obj->is_klass()) { 617 Klass* k = klassOop(obj)->klass_part(); 618 if (k->name() != NULL) { 619 ResourceMark rm; 620 const char* ext = k->external_name(); 621 if ( strcmp(_target, ext) == 0 ) { 622 tty->print_cr("Found " INTPTR_FORMAT, obj); 623 obj->print(); 624 } 625 } 626 } 627 } 628 }; 629 630 // 631 extern "C" void findclass(const char name[]) { 632 Command c("findclass"); 633 if (name != NULL) { 634 tty->print_cr("Finding class %s -> ", name); 635 FindClassObjectClosure srch(name); 636 Universe::heap()->permanent_object_iterate(&srch); 637 } 638 } 639 640 // Another interface that isn't ambiguous in dbx. 641 // Can we someday rename the other find to hsfind? 642 extern "C" void hsfind(intptr_t x) { 643 Command c("hsfind"); 644 os::print_location(tty, x, false); 645 } 646 647 648 extern "C" void hsfindref(intptr_t x) { 649 Command c("hsfindref"); 650 findref(x); 651 } 652 653 extern "C" void find(intptr_t x) { 654 Command c("find"); 655 os::print_location(tty, x, false); 656 } 657 658 659 extern "C" void findpc(intptr_t x) { 660 Command c("findpc"); 661 os::print_location(tty, x, true); 662 } 663 664 665 // int versions of all methods to avoid having to type type casts in the debugger 666 667 void pp(intptr_t p) { pp((void*)p); } 668 void pp(oop p) { pp((void*)p); } 669 670 void help() { 671 Command c("help"); 672 tty->print_cr("basic"); 673 tty->print_cr(" pp(void* p) - try to make sense of p"); 674 tty->print_cr(" pv(intptr_t p)- ((PrintableResourceObj*) p)->print()"); 675 tty->print_cr(" ps() - print current thread stack"); 676 tty->print_cr(" pss() - print all thread stacks"); 677 tty->print_cr(" pm(int pc) - print methodOop given compiled PC"); 678 tty->print_cr(" findm(intptr_t pc) - finds methodOop"); 679 tty->print_cr(" find(intptr_t x) - finds & prints nmethod/stub/bytecode/oop based on pointer into it"); 680 681 tty->print_cr("misc."); 682 tty->print_cr(" flush() - flushes the log file"); 683 tty->print_cr(" events() - dump last 50 events"); 684 685 686 tty->print_cr("compiler debugging"); 687 tty->print_cr(" debug() - to set things up for compiler debugging"); 688 tty->print_cr(" ndebug() - undo debug"); 689 } 690 691 #if 0 692 693 // BobV's command parser for debugging on windows when nothing else works. 694 695 enum CommandID { 696 CMDID_HELP, 697 CMDID_QUIT, 698 CMDID_HSFIND, 699 CMDID_PSS, 700 CMDID_PS, 701 CMDID_PSF, 702 CMDID_FINDM, 703 CMDID_FINDNM, 704 CMDID_PP, 705 CMDID_BPT, 706 CMDID_EXIT, 707 CMDID_VERIFY, 708 CMDID_THREADS, 709 CMDID_ILLEGAL = 99 710 }; 711 712 struct CommandParser { 713 char *name; 714 CommandID code; 715 char *description; 716 }; 717 718 struct CommandParser CommandList[] = { 719 (char *)"help", CMDID_HELP, " Dump this list", 720 (char *)"quit", CMDID_QUIT, " Return from this routine", 721 (char *)"hsfind", CMDID_HSFIND, "Perform an hsfind on an address", 722 (char *)"ps", CMDID_PS, " Print Current Thread Stack Trace", 723 (char *)"pss", CMDID_PSS, " Print All Thread Stack Trace", 724 (char *)"psf", CMDID_PSF, " Print All Stack Frames", 725 (char *)"findm", CMDID_FINDM, " Find a methodOop from a PC", 726 (char *)"findnm", CMDID_FINDNM, "Find an nmethod from a PC", 727 (char *)"pp", CMDID_PP, " Find out something about a pointer", 728 (char *)"break", CMDID_BPT, " Execute a breakpoint", 729 (char *)"exitvm", CMDID_EXIT, "Exit the VM", 730 (char *)"verify", CMDID_VERIFY, "Perform a Heap Verify", 731 (char *)"thread", CMDID_THREADS, "Dump Info on all Threads", 732 (char *)0, CMDID_ILLEGAL 733 }; 734 735 736 // get_debug_command() 737 // 738 // Read a command from standard input. 739 // This is useful when you have a debugger 740 // which doesn't support calling into functions. 741 // 742 void get_debug_command() 743 { 744 ssize_t count; 745 int i,j; 746 bool gotcommand; 747 intptr_t addr; 748 char buffer[256]; 749 nmethod *nm; 750 methodOop m; 751 752 tty->print_cr("You have entered the diagnostic command interpreter"); 753 tty->print("The supported commands are:\n"); 754 for ( i=0; ; i++ ) { 755 if ( CommandList[i].code == CMDID_ILLEGAL ) 756 break; 757 tty->print_cr(" %s \n", CommandList[i].name ); 758 } 759 760 while ( 1 ) { 761 gotcommand = false; 762 tty->print("Please enter a command: "); 763 count = scanf("%s", buffer) ; 764 if ( count >=0 ) { 765 for ( i=0; ; i++ ) { 766 if ( CommandList[i].code == CMDID_ILLEGAL ) { 767 if (!gotcommand) tty->print("Invalid command, please try again\n"); 768 break; 769 } 770 if ( strcmp(buffer, CommandList[i].name) == 0 ) { 771 gotcommand = true; 772 switch ( CommandList[i].code ) { 773 case CMDID_PS: 774 ps(); 775 break; 776 case CMDID_PSS: 777 pss(); 778 break; 779 case CMDID_PSF: 780 psf(); 781 break; 782 case CMDID_FINDM: 783 tty->print("Please enter the hex addr to pass to findm: "); 784 scanf("%I64X", &addr); 785 m = (methodOop)findm(addr); 786 tty->print("findm(0x%I64X) returned 0x%I64X\n", addr, m); 787 break; 788 case CMDID_FINDNM: 789 tty->print("Please enter the hex addr to pass to findnm: "); 790 scanf("%I64X", &addr); 791 nm = (nmethod*)findnm(addr); 792 tty->print("findnm(0x%I64X) returned 0x%I64X\n", addr, nm); 793 break; 794 case CMDID_PP: 795 tty->print("Please enter the hex addr to pass to pp: "); 796 scanf("%I64X", &addr); 797 pp((void*)addr); 798 break; 799 case CMDID_EXIT: 800 exit(0); 801 case CMDID_HELP: 802 tty->print("Here are the supported commands: "); 803 for ( j=0; ; j++ ) { 804 if ( CommandList[j].code == CMDID_ILLEGAL ) 805 break; 806 tty->print_cr(" %s -- %s\n", CommandList[j].name, 807 CommandList[j].description ); 808 } 809 break; 810 case CMDID_QUIT: 811 return; 812 break; 813 case CMDID_BPT: 814 BREAKPOINT; 815 break; 816 case CMDID_VERIFY: 817 verify();; 818 break; 819 case CMDID_THREADS: 820 threads();; 821 break; 822 case CMDID_HSFIND: 823 tty->print("Please enter the hex addr to pass to hsfind: "); 824 scanf("%I64X", &addr); 825 tty->print("Calling hsfind(0x%I64X)\n", addr); 826 hsfind(addr); 827 break; 828 default: 829 case CMDID_ILLEGAL: 830 break; 831 } 832 } 833 } 834 } 835 } 836 } 837 #endif 838 839 #endif // PRODUCT