src/share/vm/utilities/debug.cpp

Mon, 09 Aug 2010 17:51:56 -0700

author
never
date
Mon, 09 Aug 2010 17:51:56 -0700
changeset 2044
f4f596978298
parent 2036
126ea7725993
child 2130
30f67acf635d
permissions
-rw-r--r--

Merge

     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  */
    25 # include "incls/_precompiled.incl"
    26 # include "incls/_debug.cpp.incl"
    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
    39 #ifdef _DEBUG
    40 #  ifndef ASSERT
    41      configuration error: ASSERT must be defined in debug version
    42 #  endif // ASSERT
    43 #endif // _DEBUG
    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
    53 void warning(const char* format, ...) {
    54   // In case error happens before init or during shutdown
    55   if (tty == NULL) ostream_init();
    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 }
    65 #ifndef PRODUCT
    67 #define is_token_break(ch) (isspace(ch) || (ch) == ',')
    69 static const char* last_file_name = NULL;
    70 static int         last_line_no   = -1;
    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.
    75 bool 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;
    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;
    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   }
   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 }
   161 #undef is_token_break
   163 #else
   165 // Place-holder for non-existent suppression check:
   166 #define error_is_suppressed(file_name, line_no) (false)
   168 #endif //PRODUCT
   170 void 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 }
   179 void report_fatal(const char* file, int line, const char* message)
   180 {
   181   report_vm_error(file, line, "fatal error", message);
   182 }
   184 // Used by report_vm_out_of_memory to detect recursion.
   185 static jint _exiting_out_of_mem = 0;
   187 void 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;
   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.
   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;
   199   if (first_time_here) {
   200     Thread* thread = ThreadLocalStorage::get_thread_slow();
   201     VMError(thread, file, line, size, message).report_and_die();
   202   }
   204   // Dump core and abort
   205   vm_abort(true);
   206 }
   208 void report_should_not_call(const char* file, int line) {
   209   report_vm_error(file, line, "ShouldNotCall()");
   210 }
   212 void report_should_not_reach_here(const char* file, int line) {
   213   report_vm_error(file, line, "ShouldNotReachHere()");
   214 }
   216 void report_unimplemented(const char* file, int line) {
   217   report_vm_error(file, line, "Unimplemented()");
   218 }
   220 void 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 }
   226 void report_java_out_of_memory(const char* message) {
   227   static jint out_of_memory_reported = 0;
   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     }
   240     if (OnOutOfMemoryError && OnOutOfMemoryError[0]) {
   241       VMError err(message);
   242       err.report_java_out_of_memory();
   243     }
   244   }
   245 }
   248 extern "C" void ps();
   250 static bool error_reported = false;
   252 // call this when the VM is dying--it might loosen some asserts
   253 void set_error_reported() {
   254   error_reported = true;
   255 }
   257 bool is_error_reported() {
   258     return error_reported;
   259 }
   261 #ifndef PRODUCT
   262 #include <signal.h>
   264 void test_error_handler(size_t test_num)
   265 {
   266   if (test_num == 0) return;
   268   // If asserts are disabled, use the corresponding guarantee instead.
   269   size_t n = test_num;
   270   NOT_DEBUG(if (n <= 2) n += 2);
   272   const char* const str = "hello";
   273   const size_t      num = (size_t)os::vm_page_size();
   275   const char* const eol = os::line_separator();
   276   const char* const msg = "this message should be truncated during formatting";
   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);
   301     default: ShouldNotReachHere();
   302   }
   303 }
   304 #endif // #ifndef PRODUCT
   306 // ------ helper functions for debugging go here ------------
   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.
   313 class 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   }
   329   ~Command() { tty->flush(); Debugging = debug_save; level--; }
   330 };
   332 int Command::level = 0;
   334 extern "C" void blob(CodeBlob* cb) {
   335   Command c("blob");
   336   cb->print();
   337 }
   340 extern "C" void dump_vtable(address p) {
   341   Command c("dump_vtable");
   342   klassOop k = (klassOop)p;
   343   instanceKlass::cast(k)->vtable()->print();
   344 }
   347 extern "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 }
   359 extern "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 }
   367 extern "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 }
   379 extern "C" void universe() {
   380   Command c("universe");
   381   Universe::print();
   382 }
   385 extern "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 }
   402 extern "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 }
   414 // pv: print vm-printable object
   415 extern "C" void pa(intptr_t p)   { ((AllocatedObj*) p)->print(); }
   416 extern "C" void findpc(intptr_t x);
   418 extern "C" void ps() { // print stack
   419   Command c("ps");
   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();
   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(&reg_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, &reg_map, p));
   438   pd_ps(f);
   439   }
   441 }
   444 extern "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 }
   458 extern "C" void threads() {
   459   Command c("threads");
   460   Threads::print(false, true);
   461 }
   464 extern "C" void psd() {
   465   Command c("psd");
   466   SystemDictionary::print();
   467 }
   470 extern "C" void safepoints() {
   471   Command c("safepoints");
   472   SafepointSynchronize::print_state();
   473 }
   476 extern "C" void pss() { // print all stacks
   477   Command c("pss");
   478   Threads::print(true, true);
   479 }
   482 extern "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 }
   491 extern "C" void ndebug() {              // undo debug()
   492   Command c("ndebug");
   493   PrintCompilation = false;
   494   PrintInlining = PrintAssembly = false;
   495   tty->flush();
   496 }
   499 extern "C" void flush()  {
   500   Command c("flush");
   501   tty->flush();
   502 }
   505 extern "C" void events() {
   506   Command c("events");
   507   Events::print_last(tty, 50);
   508 }
   511 extern "C" void nevents(int n) {
   512   Command c("events");
   513   Events::print_last(tty, n);
   514 }
   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.
   521 extern "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 }
   532 extern "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 }
   539 extern "C" nmethod* findnm(intptr_t addr) {
   540   Command c("findnm");
   541   return  CodeCache::find_nmethod((address)addr);
   542 }
   544 static 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 }
   555 class LookForRefInGenClosure : public OopsInGenClosure {
   556 public:
   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 };
   567 class LookForRefInObjectClosure : public ObjectClosure {
   568 private:
   569   LookForRefInGenClosure look_in_object;
   570 public:
   571   LookForRefInObjectClosure(oop target) { look_in_object.target = target; }
   572   void do_object(oop obj) {
   573     obj->oop_iterate(&look_in_object);
   574   }
   575 };
   578 static 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);
   584   tty->print_cr("Searching heap:");
   585   ch->object_iterate(&look_in_object);
   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);
   595   tty->print_cr("Searching code cache:");
   596   CodeCache::oops_do(&lookFor);
   598   tty->print_cr("Done.");
   599 }
   601 class FindClassObjectClosure: public ObjectClosure {
   602   private:
   603     const char* _target;
   604   public:
   605     FindClassObjectClosure(const char name[])  { _target = name; }
   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 };
   622 //
   623 extern "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 }
   632 // Another interface that isn't ambiguous in dbx.
   633 // Can we someday rename the other find to hsfind?
   634 extern "C" void hsfind(intptr_t x) {
   635   Command c("hsfind");
   636   os::print_location(tty, x, false);
   637 }
   640 extern "C" void hsfindref(intptr_t x) {
   641   Command c("hsfindref");
   642   findref(x);
   643 }
   645 extern "C" void find(intptr_t x) {
   646   Command c("find");
   647   os::print_location(tty, x, false);
   648 }
   651 extern "C" void findpc(intptr_t x) {
   652   Command c("findpc");
   653   os::print_location(tty, x, true);
   654 }
   657 // int versions of all methods to avoid having to type type casts in the debugger
   659 void pp(intptr_t p)          { pp((void*)p); }
   660 void pp(oop p)               { pp((void*)p); }
   662 void 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");
   673   tty->print_cr("misc.");
   674   tty->print_cr("  flush()       - flushes the log file");
   675   tty->print_cr("  events()      - dump last 50 events");
   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 }
   683 #if 0
   685 // BobV's command parser for debugging on windows when nothing else works.
   687 enum 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 };
   704 struct CommandParser {
   705    char *name;
   706    CommandID code;
   707    char *description;
   708 };
   710 struct 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 };
   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 //
   734 void 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;
   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   }
   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
   831 #endif // PRODUCT

mercurial