debug.cpp revision 3864:f34d701e952e
11564SN/A/*
21564SN/A * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
31564SN/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
41564SN/A *
51564SN/A * This code is free software; you can redistribute it and/or modify it
61564SN/A * under the terms of the GNU General Public License version 2 only, as
71564SN/A * published by the Free Software Foundation.
81564SN/A *
91564SN/A * This code is distributed in the hope that it will be useful, but WITHOUT
101564SN/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
111564SN/A * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
121564SN/A * version 2 for more details (a copy is included in the LICENSE file that
131564SN/A * accompanied this code).
141564SN/A *
151564SN/A * You should have received a copy of the GNU General Public License version
161564SN/A * 2 along with this work; if not, write to the Free Software Foundation,
171564SN/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
181564SN/A *
191564SN/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
201564SN/A * or visit www.oracle.com if you need additional information or have any
211564SN/A * questions.
221564SN/A *
231564SN/A */
241564SN/A
251564SN/A#include "precompiled.hpp"
261564SN/A#include "classfile/systemDictionary.hpp"
271564SN/A#include "code/codeCache.hpp"
281564SN/A#include "code/icBuffer.hpp"
291564SN/A#include "code/nmethod.hpp"
301564SN/A#include "code/vtableStubs.hpp"
311564SN/A#include "compiler/compileBroker.hpp"
321564SN/A#include "compiler/disassembler.hpp"
331564SN/A#include "gc_implementation/shared/markSweep.hpp"
341564SN/A#include "gc_interface/collectedHeap.hpp"
351564SN/A#include "interpreter/bytecodeHistogram.hpp"
361564SN/A#include "interpreter/interpreter.hpp"
371564SN/A#include "memory/resourceArea.hpp"
381564SN/A#include "memory/universe.hpp"
391564SN/A#include "oops/oop.inline.hpp"
401565Ssundar#include "prims/privilegedStack.hpp"
411564SN/A#include "runtime/arguments.hpp"
421564SN/A#include "runtime/frame.hpp"
431564SN/A#include "runtime/java.hpp"
441564SN/A#include "runtime/sharedRuntime.hpp"
451564SN/A#include "runtime/stubCodeGenerator.hpp"
461564SN/A#include "runtime/stubRoutines.hpp"
471564SN/A#include "runtime/thread.inline.hpp"
481564SN/A#include "runtime/vframe.hpp"
491564SN/A#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
91FormatBufferResource::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
99void 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
116static const char* last_file_name = NULL;
117static 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.
122bool 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
217void 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
226void report_fatal(const char* file, int line, const char* message)
227{
228  report_vm_error(file, line, "fatal error", message);
229}
230
231// Used by report_vm_out_of_memory to detect recursion.
232static jint _exiting_out_of_mem = 0;
233
234void report_vm_out_of_memory(const char* file, int line, size_t size,
235                             const char* message) {
236  if (Debugging) return;
237
238  // We try to gather additional information for the first out of memory
239  // error only; gathering additional data might cause an allocation and a
240  // recursive out_of_memory condition.
241
242  const jint exiting = 1;
243  // If we succeed in changing the value, we're the first one in.
244  bool first_time_here = Atomic::xchg(exiting, &_exiting_out_of_mem) != exiting;
245
246  if (first_time_here) {
247    Thread* thread = ThreadLocalStorage::get_thread_slow();
248    VMError(thread, file, line, size, message).report_and_die();
249  }
250
251  // Dump core and abort
252  vm_abort(true);
253}
254
255void report_should_not_call(const char* file, int line) {
256  report_vm_error(file, line, "ShouldNotCall()");
257}
258
259void report_should_not_reach_here(const char* file, int line) {
260  report_vm_error(file, line, "ShouldNotReachHere()");
261}
262
263void report_should_not_reach_here2(const char* file, int line, const char* message) {
264  report_vm_error(file, line, "ShouldNotReachHere()", message);
265}
266
267void report_unimplemented(const char* file, int line) {
268  report_vm_error(file, line, "Unimplemented()");
269}
270
271void report_untested(const char* file, int line, const char* message) {
272#ifndef PRODUCT
273  warning("Untested: %s in %s: %d\n", message, file, line);
274#endif // !PRODUCT
275}
276
277void report_out_of_shared_space(SharedSpaceType shared_space) {
278  static const char* name[] = {
279    "native memory for metadata",
280    "shared read only space",
281    "shared read write space",
282    "shared miscellaneous data space"
283  };
284  static const char* flag[] = {
285    "Metaspace",
286    "SharedReadOnlySize",
287    "SharedReadWriteSize",
288    "SharedMiscDataSize"
289  };
290
291   warning("\nThe %s is not large enough\n"
292           "to preload requested classes. Use -XX:%s=\n"
293           "to increase the initial size of %s.\n",
294           name[shared_space], flag[shared_space], name[shared_space]);
295   exit(2);
296}
297
298void report_java_out_of_memory(const char* message) {
299  static jint out_of_memory_reported = 0;
300
301  // A number of threads may attempt to report OutOfMemoryError at around the
302  // same time. To avoid dumping the heap or executing the data collection
303  // commands multiple times we just do it once when the first threads reports
304  // the error.
305  if (Atomic::cmpxchg(1, &out_of_memory_reported, 0) == 0) {
306    // create heap dump before OnOutOfMemoryError commands are executed
307    if (HeapDumpOnOutOfMemoryError) {
308      tty->print_cr("java.lang.OutOfMemoryError: %s", message);
309      HeapDumper::dump_heap_from_oome();
310    }
311
312    if (OnOutOfMemoryError && OnOutOfMemoryError[0]) {
313      VMError err(message);
314      err.report_java_out_of_memory();
315    }
316  }
317}
318
319static bool error_reported = false;
320
321// call this when the VM is dying--it might loosen some asserts
322void set_error_reported() {
323  error_reported = true;
324}
325
326bool is_error_reported() {
327    return error_reported;
328}
329
330#ifndef PRODUCT
331#include <signal.h>
332
333void test_error_handler(size_t test_num)
334{
335  if (test_num == 0) return;
336
337  // If asserts are disabled, use the corresponding guarantee instead.
338  size_t n = test_num;
339  NOT_DEBUG(if (n <= 2) n += 2);
340
341  const char* const str = "hello";
342  const size_t      num = (size_t)os::vm_page_size();
343
344  const char* const eol = os::line_separator();
345  const char* const msg = "this message should be truncated during formatting";
346
347  // Keep this in sync with test/runtime/6888954/vmerrors.sh.
348  switch (n) {
349    case  1: assert(str == NULL, "expected null");
350    case  2: assert(num == 1023 && *str == 'X',
351                    err_msg("num=" SIZE_FORMAT " str=\"%s\"", num, str));
352    case  3: guarantee(str == NULL, "expected null");
353    case  4: guarantee(num == 1023 && *str == 'X',
354                       err_msg("num=" SIZE_FORMAT " str=\"%s\"", num, str));
355    case  5: fatal("expected null");
356    case  6: fatal(err_msg("num=" SIZE_FORMAT " str=\"%s\"", num, str));
357    case  7: fatal(err_msg("%s%s#    %s%s#    %s%s#    %s%s#    %s%s#    "
358                           "%s%s#    %s%s#    %s%s#    %s%s#    %s%s#    "
359                           "%s%s#    %s%s#    %s%s#    %s%s#    %s",
360                           msg, eol, msg, eol, msg, eol, msg, eol, msg, eol,
361                           msg, eol, msg, eol, msg, eol, msg, eol, msg, eol,
362                           msg, eol, msg, eol, msg, eol, msg, eol, msg));
363    case  8: vm_exit_out_of_memory(num, "ChunkPool::allocate");
364    case  9: ShouldNotCallThis();
365    case 10: ShouldNotReachHere();
366    case 11: Unimplemented();
367    // This is last because it does not generate an hs_err* file on Windows.
368    case 12: os::signal_raise(SIGSEGV);
369
370    default: ShouldNotReachHere();
371  }
372}
373#endif // !PRODUCT
374
375// ------ helper functions for debugging go here ------------
376
377// All debug entries should be wrapped with a stack allocated
378// Command object. It makes sure a resource mark is set and
379// flushes the logfile to prevent file sharing problems.
380
381class Command : public StackObj {
382 private:
383  ResourceMark rm;
384  ResetNoHandleMark rnhm;
385  HandleMark   hm;
386  bool debug_save;
387 public:
388  static int level;
389  Command(const char* str) {
390    debug_save = Debugging;
391    Debugging = true;
392    if (level++ > 0)  return;
393    tty->cr();
394    tty->print_cr("\"Executing %s\"", str);
395  }
396
397  ~Command() {
398        tty->flush();
399        Debugging = debug_save;
400        level--;
401  }
402};
403
404int Command::level = 0;
405
406#ifndef PRODUCT
407
408extern "C" void blob(CodeBlob* cb) {
409  Command c("blob");
410  cb->print();
411}
412
413
414extern "C" void dump_vtable(address p) {
415  Command c("dump_vtable");
416  Klass* k = (Klass*)p;
417  InstanceKlass::cast(k)->vtable()->print();
418}
419
420
421extern "C" void nm(intptr_t p) {
422  // Actually we look through all CodeBlobs (the nm name has been kept for backwards compatability)
423  Command c("nm");
424  CodeBlob* cb = CodeCache::find_blob((address)p);
425  if (cb == NULL) {
426    tty->print_cr("NULL");
427  } else {
428    cb->print();
429  }
430}
431
432
433extern "C" void disnm(intptr_t p) {
434  Command c("disnm");
435  CodeBlob* cb = CodeCache::find_blob((address) p);
436  nmethod* nm = cb->as_nmethod_or_null();
437  if (nm) {
438    nm->print();
439    Disassembler::decode(nm);
440  } else {
441    cb->print();
442    Disassembler::decode(cb);
443  }
444}
445
446
447extern "C" void printnm(intptr_t p) {
448  char buffer[256];
449  sprintf(buffer, "printnm: " INTPTR_FORMAT, p);
450  Command c(buffer);
451  CodeBlob* cb = CodeCache::find_blob((address) p);
452  if (cb->is_nmethod()) {
453    nmethod* nm = (nmethod*)cb;
454    nm->print_nmethod(true);
455  }
456}
457
458
459extern "C" void universe() {
460  Command c("universe");
461  Universe::print();
462}
463
464
465extern "C" void verify() {
466  // try to run a verify on the entire system
467  // note: this may not be safe if we're not at a safepoint; for debugging,
468  // this manipulates the safepoint settings to avoid assertion failures
469  Command c("universe verify");
470  bool safe = SafepointSynchronize::is_at_safepoint();
471  if (!safe) {
472    tty->print_cr("warning: not at safepoint -- verify may fail");
473    SafepointSynchronize::set_is_at_safepoint();
474  }
475  // Ensure Eden top is correct before verification
476  Universe::heap()->prepare_for_verify();
477  Universe::verify();
478  if (!safe) SafepointSynchronize::set_is_not_at_safepoint();
479}
480
481
482extern "C" void pp(void* p) {
483  Command c("pp");
484  FlagSetting fl(PrintVMMessages, true);
485  FlagSetting f2(DisplayVMOutput, true);
486  if (Universe::heap()->is_in(p)) {
487    oop obj = oop(p);
488    obj->print();
489  } else {
490    tty->print(PTR_FORMAT, p);
491  }
492}
493
494
495// pv: print vm-printable object
496extern "C" void pa(intptr_t p)   { ((AllocatedObj*) p)->print(); }
497extern "C" void findpc(intptr_t x);
498
499#endif // !PRODUCT
500
501extern "C" void ps() { // print stack
502  if (Thread::current() == NULL) return;
503  Command c("ps");
504
505
506  // Prints the stack of the current Java thread
507  JavaThread* p = JavaThread::active();
508  tty->print(" for thread: ");
509  p->print();
510  tty->cr();
511
512  if (p->has_last_Java_frame()) {
513    // If the last_Java_fp is set we are in C land and
514    // can call the standard stack_trace function.
515#ifdef PRODUCT
516    p->print_stack();
517  } else {
518    tty->print_cr("Cannot find the last Java frame, printing stack disabled.");
519#else // !PRODUCT
520    p->trace_stack();
521  } else {
522    frame f = os::current_frame();
523    RegisterMap reg_map(p);
524    f = f.sender(&reg_map);
525    tty->print("(guessing starting frame id=%#p based on current fp)\n", f.id());
526    p->trace_stack_from(vframe::new_vframe(&f, &reg_map, p));
527  pd_ps(f);
528#endif // PRODUCT
529  }
530
531}
532
533extern "C" void pfl() {
534  // print frame layout
535  Command c("pfl");
536  JavaThread* p = JavaThread::active();
537  tty->print(" for thread: ");
538  p->print();
539  tty->cr();
540  if (p->has_last_Java_frame()) {
541    p->print_frame_layout();
542  }
543}
544
545#ifndef PRODUCT
546
547extern "C" void psf() { // print stack frames
548  {
549    Command c("psf");
550    JavaThread* p = JavaThread::active();
551    tty->print(" for thread: ");
552    p->print();
553    tty->cr();
554    if (p->has_last_Java_frame()) {
555      p->trace_frames();
556    }
557  }
558}
559
560
561extern "C" void threads() {
562  Command c("threads");
563  Threads::print(false, true);
564}
565
566
567extern "C" void psd() {
568  Command c("psd");
569  SystemDictionary::print();
570}
571
572
573extern "C" void safepoints() {
574  Command c("safepoints");
575  SafepointSynchronize::print_state();
576}
577
578#endif // !PRODUCT
579
580extern "C" void pss() { // print all stacks
581  if (Thread::current() == NULL) return;
582  Command c("pss");
583  Threads::print(true, PRODUCT_ONLY(false) NOT_PRODUCT(true));
584}
585
586#ifndef PRODUCT
587
588extern "C" void debug() {               // to set things up for compiler debugging
589  Command c("debug");
590  WizardMode = true;
591  PrintVMMessages = PrintCompilation = true;
592  PrintInlining = PrintAssembly = true;
593  tty->flush();
594}
595
596
597extern "C" void ndebug() {              // undo debug()
598  Command c("ndebug");
599  PrintCompilation = false;
600  PrintInlining = PrintAssembly = false;
601  tty->flush();
602}
603
604
605extern "C" void flush()  {
606  Command c("flush");
607  tty->flush();
608}
609
610extern "C" void events() {
611  Command c("events");
612  Events::print();
613}
614
615// Given a heap address that was valid before the most recent GC, if
616// the oop that used to contain it is still live, prints the new
617// location of the oop and the address. Useful for tracking down
618// certain kinds of naked oop and oop map bugs.
619extern "C" void pnl(intptr_t old_heap_addr) {
620  // Print New Location of old heap address
621  Command c("pnl");
622#ifndef VALIDATE_MARK_SWEEP
623  tty->print_cr("Requires build with VALIDATE_MARK_SWEEP defined (debug build) and RecordMarkSweepCompaction enabled");
624#else
625  MarkSweep::print_new_location_of_heap_address((HeapWord*) old_heap_addr);
626#endif
627}
628
629
630extern "C" Method* findm(intptr_t pc) {
631  Command c("findm");
632  nmethod* nm = CodeCache::find_nmethod((address)pc);
633  return (nm == NULL) ? (Method*)NULL : nm->method();
634}
635
636
637extern "C" nmethod* findnm(intptr_t addr) {
638  Command c("findnm");
639  return  CodeCache::find_nmethod((address)addr);
640}
641
642static address same_page(address x, address y) {
643  intptr_t page_bits = -os::vm_page_size();
644  if ((intptr_t(x) & page_bits) == (intptr_t(y) & page_bits)) {
645    return x;
646  } else if (x > y) {
647    return (address)(intptr_t(y) | ~page_bits) + 1;
648  } else {
649    return (address)(intptr_t(y) & page_bits);
650  }
651}
652
653
654// Another interface that isn't ambiguous in dbx.
655// Can we someday rename the other find to hsfind?
656extern "C" void hsfind(intptr_t x) {
657  Command c("hsfind");
658  os::print_location(tty, x, false);
659}
660
661
662extern "C" void find(intptr_t x) {
663  Command c("find");
664  os::print_location(tty, x, false);
665}
666
667
668extern "C" void findpc(intptr_t x) {
669  Command c("findpc");
670  os::print_location(tty, x, true);
671}
672
673
674// Need method pointer to find bcp, when not in permgen.
675extern "C" void findbcp(intptr_t method, intptr_t bcp) {
676  Command c("findbcp");
677  Method* mh = (Method*)method;
678  if (!mh->is_native()) {
679    tty->print_cr("bci_from(%p) = %d; print_codes():",
680                        mh, mh->bci_from(address(bcp)));
681    mh->print_codes_on(tty);
682  }
683}
684
685// int versions of all methods to avoid having to type type casts in the debugger
686
687void pp(intptr_t p)          { pp((void*)p); }
688void pp(oop p)               { pp((void*)p); }
689
690void help() {
691  Command c("help");
692  tty->print_cr("basic");
693  tty->print_cr("  pp(void* p)   - try to make sense of p");
694  tty->print_cr("  pv(intptr_t p)- ((PrintableResourceObj*) p)->print()");
695  tty->print_cr("  ps()          - print current thread stack");
696  tty->print_cr("  pss()         - print all thread stacks");
697  tty->print_cr("  pm(int pc)    - print Method* given compiled PC");
698  tty->print_cr("  findm(intptr_t pc) - finds Method*");
699  tty->print_cr("  find(intptr_t x)   - finds & prints nmethod/stub/bytecode/oop based on pointer into it");
700
701  tty->print_cr("misc.");
702  tty->print_cr("  flush()       - flushes the log file");
703  tty->print_cr("  events()      - dump events from ring buffers");
704
705
706  tty->print_cr("compiler debugging");
707  tty->print_cr("  debug()       - to set things up for compiler debugging");
708  tty->print_cr("  ndebug()      - undo debug");
709}
710
711#if 0
712
713// BobV's command parser for debugging on windows when nothing else works.
714
715enum CommandID {
716  CMDID_HELP,
717  CMDID_QUIT,
718  CMDID_HSFIND,
719  CMDID_PSS,
720  CMDID_PS,
721  CMDID_PSF,
722  CMDID_FINDM,
723  CMDID_FINDNM,
724  CMDID_PP,
725  CMDID_BPT,
726  CMDID_EXIT,
727  CMDID_VERIFY,
728  CMDID_THREADS,
729  CMDID_ILLEGAL = 99
730};
731
732struct CommandParser {
733   char *name;
734   CommandID code;
735   char *description;
736};
737
738struct CommandParser CommandList[] = {
739  (char *)"help", CMDID_HELP, "  Dump this list",
740  (char *)"quit", CMDID_QUIT, "  Return from this routine",
741  (char *)"hsfind", CMDID_HSFIND, "Perform an hsfind on an address",
742  (char *)"ps", CMDID_PS, "    Print Current Thread Stack Trace",
743  (char *)"pss", CMDID_PSS, "   Print All Thread Stack Trace",
744  (char *)"psf", CMDID_PSF, "   Print All Stack Frames",
745  (char *)"findm", CMDID_FINDM, " Find a Method* from a PC",
746  (char *)"findnm", CMDID_FINDNM, "Find an nmethod from a PC",
747  (char *)"pp", CMDID_PP, "    Find out something about a pointer",
748  (char *)"break", CMDID_BPT, " Execute a breakpoint",
749  (char *)"exitvm", CMDID_EXIT, "Exit the VM",
750  (char *)"verify", CMDID_VERIFY, "Perform a Heap Verify",
751  (char *)"thread", CMDID_THREADS, "Dump Info on all Threads",
752  (char *)0, CMDID_ILLEGAL
753};
754
755
756// get_debug_command()
757//
758// Read a command from standard input.
759// This is useful when you have a debugger
760// which doesn't support calling into functions.
761//
762void get_debug_command()
763{
764  ssize_t count;
765  int i,j;
766  bool gotcommand;
767  intptr_t addr;
768  char buffer[256];
769  nmethod *nm;
770  Method* m;
771
772  tty->print_cr("You have entered the diagnostic command interpreter");
773  tty->print("The supported commands are:\n");
774  for ( i=0; ; i++ ) {
775    if ( CommandList[i].code == CMDID_ILLEGAL )
776      break;
777    tty->print_cr("  %s \n", CommandList[i].name );
778  }
779
780  while ( 1 ) {
781    gotcommand = false;
782    tty->print("Please enter a command: ");
783    count = scanf("%s", buffer) ;
784    if ( count >=0 ) {
785      for ( i=0; ; i++ ) {
786        if ( CommandList[i].code == CMDID_ILLEGAL ) {
787          if (!gotcommand) tty->print("Invalid command, please try again\n");
788          break;
789        }
790        if ( strcmp(buffer, CommandList[i].name) == 0 ) {
791          gotcommand = true;
792          switch ( CommandList[i].code ) {
793              case CMDID_PS:
794                ps();
795                break;
796              case CMDID_PSS:
797                pss();
798                break;
799              case CMDID_PSF:
800                psf();
801                break;
802              case CMDID_FINDM:
803                tty->print("Please enter the hex addr to pass to findm: ");
804                scanf("%I64X", &addr);
805                m = (Method*)findm(addr);
806                tty->print("findm(0x%I64X) returned 0x%I64X\n", addr, m);
807                break;
808              case CMDID_FINDNM:
809                tty->print("Please enter the hex addr to pass to findnm: ");
810                scanf("%I64X", &addr);
811                nm = (nmethod*)findnm(addr);
812                tty->print("findnm(0x%I64X) returned 0x%I64X\n", addr, nm);
813                break;
814              case CMDID_PP:
815                tty->print("Please enter the hex addr to pass to pp: ");
816                scanf("%I64X", &addr);
817                pp((void*)addr);
818                break;
819              case CMDID_EXIT:
820                exit(0);
821              case CMDID_HELP:
822                tty->print("Here are the supported commands: ");
823                for ( j=0; ; j++ ) {
824                  if ( CommandList[j].code == CMDID_ILLEGAL )
825                    break;
826                  tty->print_cr("  %s --  %s\n", CommandList[j].name,
827                                                 CommandList[j].description );
828                }
829                break;
830              case CMDID_QUIT:
831                return;
832                break;
833              case CMDID_BPT:
834                BREAKPOINT;
835                break;
836              case CMDID_VERIFY:
837                verify();;
838                break;
839              case CMDID_THREADS:
840                threads();;
841                break;
842              case CMDID_HSFIND:
843                tty->print("Please enter the hex addr to pass to hsfind: ");
844                scanf("%I64X", &addr);
845                tty->print("Calling hsfind(0x%I64X)\n", addr);
846                hsfind(addr);
847                break;
848              default:
849              case CMDID_ILLEGAL:
850                break;
851          }
852        }
853      }
854    }
855  }
856}
857#endif
858
859#endif // !PRODUCT
860