src/share/vm/utilities/debug.cpp

Sat, 11 Dec 2010 13:20:56 -0500

author
zgu
date
Sat, 11 Dec 2010 13:20:56 -0500
changeset 2364
2d4762ec74af
parent 2314
f95d63e2154a
child 2350
2f644f85485d
permissions
-rw-r--r--

7003748: Decode C stack frames when symbols are presented (PhoneHome project)
Summary: Implemented in-process C native stack frame decoding when symbols are available.
Reviewed-by: coleenp, never

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

mercurial