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