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