debug.cpp revision 0:a61af66fc99e
1/*
2 * Copyright 1997-2007 Sun Microsystems, Inc.  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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
20 * CA 95054 USA or visit www.sun.com if you need additional information or
21 * have any questions.
22 *
23 */
24
25# include "incls/_precompiled.incl"
26# include "incls/_debug.cpp.incl"
27
28#ifndef ASSERT
29#  ifdef _DEBUG
30   // NOTE: don't turn the lines below into a comment -- if you're getting
31   // a compile error here, change the settings to define ASSERT
32   ASSERT should be defined when _DEBUG is defined.  It is not intended to be used for debugging
33   functions that do not slow down the system too much and thus can be left in optimized code.
34   On the other hand, the code should not be included in a production version.
35#  endif // _DEBUG
36#endif // ASSERT
37
38
39#ifdef _DEBUG
40#  ifndef ASSERT
41     configuration error: ASSERT must be defined in debug version
42#  endif // ASSERT
43#endif // _DEBUG
44
45
46#ifdef PRODUCT
47#  if -defined _DEBUG || -defined ASSERT
48     configuration error: ASSERT et al. must not be defined in PRODUCT version
49#  endif
50#endif // PRODUCT
51
52
53void warning(const char* format, ...) {
54  // In case error happens before init or during shutdown
55  if (tty == NULL) ostream_init();
56
57  tty->print("%s warning: ", VM_Version::vm_name());
58  va_list ap;
59  va_start(ap, format);
60  tty->vprint_cr(format, ap);
61  va_end(ap);
62  if (BreakAtWarning) BREAKPOINT;
63}
64
65#ifndef PRODUCT
66
67#define is_token_break(ch) (isspace(ch) || (ch) == ',')
68
69static const char* last_file_name = NULL;
70static int         last_line_no   = -1;
71
72// assert/guarantee/... may happen very early during VM initialization.
73// Don't rely on anything that is initialized by Threads::create_vm(). For
74// example, don't use tty.
75bool assert_is_suppressed(const char* file_name, int line_no) {
76  // The following 1-element cache requires that passed-in
77  // file names are always only constant literals.
78  if (file_name == last_file_name && line_no == last_line_no)  return true;
79
80  int file_name_len = (int)strlen(file_name);
81  char separator = os::file_separator()[0];
82  const char* base_name = strrchr(file_name, separator);
83  if (base_name == NULL)
84    base_name = file_name;
85
86  // scan the SuppressErrorAt option
87  const char* cp = SuppressErrorAt;
88  for (;;) {
89    const char* sfile;
90    int sfile_len;
91    int sline;
92    bool noisy;
93    while ((*cp) != '\0' && is_token_break(*cp))  cp++;
94    if ((*cp) == '\0')  break;
95    sfile = cp;
96    while ((*cp) != '\0' && !is_token_break(*cp) && (*cp) != ':')  cp++;
97    sfile_len = cp - sfile;
98    if ((*cp) == ':')  cp++;
99    sline = 0;
100    while ((*cp) != '\0' && isdigit(*cp)) {
101      sline *= 10;
102      sline += (*cp) - '0';
103      cp++;
104    }
105    // "file:line!" means the assert suppression is not silent
106    noisy = ((*cp) == '!');
107    while ((*cp) != '\0' && !is_token_break(*cp))  cp++;
108    // match the line
109    if (sline != 0) {
110      if (sline != line_no)  continue;
111    }
112    // match the file
113    if (sfile_len > 0) {
114      const char* look = file_name;
115      const char* look_max = file_name + file_name_len - sfile_len;
116      const char* foundp;
117      bool match = false;
118      while (!match
119             && (foundp = strchr(look, sfile[0])) != NULL
120             && foundp <= look_max) {
121        match = true;
122        for (int i = 1; i < sfile_len; i++) {
123          if (sfile[i] != foundp[i]) {
124            match = false;
125            break;
126          }
127        }
128        look = foundp + 1;
129      }
130      if (!match)  continue;
131    }
132    // got a match!
133    if (noisy) {
134      fdStream out(defaultStream::output_fd());
135      out.print_raw("[error suppressed at ");
136      out.print_raw(base_name);
137      char buf[16];
138      jio_snprintf(buf, sizeof(buf), ":%d]", line_no);
139      out.print_raw_cr(buf);
140    } else {
141      // update 1-element cache for fast silent matches
142      last_file_name = file_name;
143      last_line_no   = line_no;
144    }
145    return true;
146  }
147
148  if (!is_error_reported()) {
149    // print a friendly hint:
150    fdStream out(defaultStream::output_fd());
151    out.print_raw_cr("# To suppress the following error report, specify this argument");
152    out.print_raw   ("# after -XX: or in .hotspotrc:  SuppressErrorAt=");
153    out.print_raw   (base_name);
154    char buf[16];
155    jio_snprintf(buf, sizeof(buf), ":%d", line_no);
156    out.print_raw_cr(buf);
157  }
158  return false;
159}
160
161#undef is_token_break
162
163#else
164
165// Place-holder for non-existent suppression check:
166#define assert_is_suppressed(file_name, line_no) (false)
167
168#endif //PRODUCT
169
170void report_assertion_failure(const char* file_name, int line_no, const char* message) {
171  if (Debugging || assert_is_suppressed(file_name, line_no))  return;
172  VMError err(ThreadLocalStorage::get_thread_slow(), message, file_name, line_no);
173  err.report_and_die();
174}
175
176void report_fatal(const char* file_name, int line_no, const char* message) {
177  if (Debugging || assert_is_suppressed(file_name, line_no))  return;
178  VMError err(ThreadLocalStorage::get_thread_slow(), message, file_name, line_no);
179  err.report_and_die();
180}
181
182void report_fatal_vararg(const char* file_name, int line_no, const char* format, ...) {
183  char buffer[256];
184  va_list ap;
185  va_start(ap, format);
186  jio_vsnprintf(buffer, sizeof(buffer), format, ap);
187  va_end(ap);
188  report_fatal(file_name, line_no, buffer);
189}
190
191
192// Used by report_vm_out_of_memory to detect recursion.
193static jint _exiting_out_of_mem = 0;
194
195// Just passing the flow to VMError to handle error
196void report_vm_out_of_memory(const char* file_name, int line_no, size_t size, const char* message) {
197  if (Debugging || assert_is_suppressed(file_name, line_no))  return;
198
199  // We try to gather additional information for the first out of memory
200  // error only; gathering additional data might cause an allocation and a
201  // recursive out_of_memory condition.
202
203  const jint exiting = 1;
204  // If we succeed in changing the value, we're the first one in.
205  bool first_time_here = Atomic::xchg(exiting, &_exiting_out_of_mem) != exiting;
206
207  if (first_time_here) {
208    Thread* thread = ThreadLocalStorage::get_thread_slow();
209    VMError(thread, size, message, file_name, line_no).report_and_die();
210  }
211  vm_abort();
212}
213
214void report_vm_out_of_memory_vararg(const char* file_name, int line_no, size_t size, const char* format, ...) {
215  char buffer[256];
216  va_list ap;
217  va_start(ap, format);
218  jio_vsnprintf(buffer, sizeof(buffer), format, ap);
219  va_end(ap);
220  report_vm_out_of_memory(file_name, line_no, size, buffer);
221}
222
223void report_should_not_call(const char* file_name, int line_no) {
224  if (Debugging || assert_is_suppressed(file_name, line_no))  return;
225  VMError err(ThreadLocalStorage::get_thread_slow(), "ShouldNotCall()", file_name, line_no);
226  err.report_and_die();
227}
228
229
230void report_should_not_reach_here(const char* file_name, int line_no) {
231  if (Debugging || assert_is_suppressed(file_name, line_no))  return;
232  VMError err(ThreadLocalStorage::get_thread_slow(), "ShouldNotReachHere()", file_name, line_no);
233  err.report_and_die();
234}
235
236
237void report_unimplemented(const char* file_name, int line_no) {
238  if (Debugging || assert_is_suppressed(file_name, line_no))  return;
239  VMError err(ThreadLocalStorage::get_thread_slow(), "Unimplemented()", file_name, line_no);
240  err.report_and_die();
241}
242
243
244void report_untested(const char* file_name, int line_no, const char* msg) {
245#ifndef PRODUCT
246  warning("Untested: %s in %s: %d\n", msg, file_name, line_no);
247#endif // PRODUCT
248}
249
250void report_java_out_of_memory(const char* message) {
251  static jint out_of_memory_reported = 0;
252
253  // A number of threads may attempt to report OutOfMemoryError at around the
254  // same time. To avoid dumping the heap or executing the data collection
255  // commands multiple times we just do it once when the first threads reports
256  // the error.
257  if (Atomic::cmpxchg(1, &out_of_memory_reported, 0) == 0) {
258    // create heap dump before OnOutOfMemoryError commands are executed
259    if (HeapDumpOnOutOfMemoryError) {
260      tty->print_cr("java.lang.OutOfMemoryError: %s", message);
261      HeapDumper::dump_heap();
262    }
263
264    if (OnOutOfMemoryError && OnOutOfMemoryError[0]) {
265      VMError err(message);
266      err.report_java_out_of_memory();
267    }
268  }
269}
270
271
272extern "C" void ps();
273
274static bool error_reported = false;
275
276// call this when the VM is dying--it might loosen some asserts
277void set_error_reported() {
278  error_reported = true;
279}
280
281bool is_error_reported() {
282    return error_reported;
283}
284
285// ------ helper functions for debugging go here ------------
286
287#ifndef PRODUCT
288// All debug entries should be wrapped with a stack allocated
289// Command object. It makes sure a resource mark is set and
290// flushes the logfile to prevent file sharing problems.
291
292class Command : public StackObj {
293 private:
294  ResourceMark rm;
295  ResetNoHandleMark rnhm;
296  HandleMark   hm;
297  bool debug_save;
298 public:
299  static int level;
300  Command(const char* str) {
301    debug_save = Debugging;
302    Debugging = true;
303    if (level++ > 0)  return;
304    tty->cr();
305    tty->print_cr("\"Executing %s\"", str);
306  }
307
308  ~Command() { tty->flush(); Debugging = debug_save; level--; }
309};
310
311int Command::level = 0;
312
313extern "C" void blob(CodeBlob* cb) {
314  Command c("blob");
315  cb->print();
316}
317
318
319extern "C" void dump_vtable(address p) {
320  Command c("dump_vtable");
321  klassOop k = (klassOop)p;
322  instanceKlass::cast(k)->vtable()->print();
323}
324
325
326extern "C" void nm(intptr_t p) {
327  // Actually we look through all CodeBlobs (the nm name has been kept for backwards compatability)
328  Command c("nm");
329  CodeBlob* cb = CodeCache::find_blob((address)p);
330  if (cb == NULL) {
331    tty->print_cr("NULL");
332  } else {
333    cb->print();
334  }
335}
336
337
338extern "C" void disnm(intptr_t p) {
339  Command c("disnm");
340  CodeBlob* cb = CodeCache::find_blob((address) p);
341  cb->print();
342  Disassembler::decode(cb);
343}
344
345
346extern "C" void printnm(intptr_t p) {
347  char buffer[256];
348  sprintf(buffer, "printnm: " INTPTR_FORMAT, p);
349  Command c(buffer);
350  CodeBlob* cb = CodeCache::find_blob((address) p);
351  if (cb->is_nmethod()) {
352    nmethod* nm = (nmethod*)cb;
353    nm->print_nmethod(true);
354  }
355}
356
357
358extern "C" void universe() {
359  Command c("universe");
360  Universe::print();
361}
362
363
364extern "C" void verify() {
365  // try to run a verify on the entire system
366  // note: this may not be safe if we're not at a safepoint; for debugging,
367  // this manipulates the safepoint settings to avoid assertion failures
368  Command c("universe verify");
369  bool safe = SafepointSynchronize::is_at_safepoint();
370  if (!safe) {
371    tty->print_cr("warning: not at safepoint -- verify may fail");
372    SafepointSynchronize::set_is_at_safepoint();
373  }
374  // Ensure Eden top is correct before verification
375  Universe::heap()->prepare_for_verify();
376  Universe::verify(true);
377  if (!safe) SafepointSynchronize::set_is_not_at_safepoint();
378}
379
380
381extern "C" void pp(void* p) {
382  Command c("pp");
383  FlagSetting fl(PrintVMMessages, true);
384  if (Universe::heap()->is_in(p)) {
385    oop obj = oop(p);
386    obj->print();
387  } else {
388    tty->print("%#p", p);
389  }
390}
391
392
393// pv: print vm-printable object
394extern "C" void pa(intptr_t p)   { ((AllocatedObj*) p)->print(); }
395extern "C" void findpc(intptr_t x);
396
397extern "C" void ps() { // print stack
398  Command c("ps");
399
400
401  // Prints the stack of the current Java thread
402  JavaThread* p = JavaThread::active();
403  tty->print(" for thread: ");
404  p->print();
405  tty->cr();
406
407  if (p->has_last_Java_frame()) {
408    // If the last_Java_fp is set we are in C land and
409    // can call the standard stack_trace function.
410    p->trace_stack();
411  } else {
412    frame f = os::current_frame();
413    RegisterMap reg_map(p);
414    f = f.sender(&reg_map);
415    tty->print("(guessing starting frame id=%#p based on current fp)\n", f.id());
416    p->trace_stack_from(vframe::new_vframe(&f, &reg_map, p));
417  pd_ps(f);
418  }
419
420}
421
422
423extern "C" void psf() { // print stack frames
424  {
425    Command c("psf");
426    JavaThread* p = JavaThread::active();
427    tty->print(" for thread: ");
428    p->print();
429    tty->cr();
430    if (p->has_last_Java_frame()) {
431      p->trace_frames();
432    }
433  }
434}
435
436
437extern "C" void threads() {
438  Command c("threads");
439  Threads::print(false, true);
440}
441
442
443extern "C" void psd() {
444  Command c("psd");
445  SystemDictionary::print();
446}
447
448
449extern "C" void safepoints() {
450  Command c("safepoints");
451  SafepointSynchronize::print_state();
452}
453
454
455extern "C" void pss() { // print all stacks
456  Command c("pss");
457  Threads::print(true, true);
458}
459
460
461extern "C" void debug() {               // to set things up for compiler debugging
462  Command c("debug");
463  WizardMode = true;
464  PrintVMMessages = PrintCompilation = true;
465  PrintInlining = PrintAssembly = true;
466  tty->flush();
467}
468
469
470extern "C" void ndebug() {              // undo debug()
471  Command c("ndebug");
472  PrintCompilation = false;
473  PrintInlining = PrintAssembly = false;
474  tty->flush();
475}
476
477
478extern "C" void flush()  {
479  Command c("flush");
480  tty->flush();
481}
482
483
484extern "C" void events() {
485  Command c("events");
486  Events::print_last(tty, 50);
487}
488
489
490extern "C" void nevents(int n) {
491  Command c("events");
492  Events::print_last(tty, n);
493}
494
495
496// Given a heap address that was valid before the most recent GC, if
497// the oop that used to contain it is still live, prints the new
498// location of the oop and the address. Useful for tracking down
499// certain kinds of naked oop and oop map bugs.
500extern "C" void pnl(intptr_t old_heap_addr) {
501  // Print New Location of old heap address
502  Command c("pnl");
503#ifndef VALIDATE_MARK_SWEEP
504  tty->print_cr("Requires build with VALIDATE_MARK_SWEEP defined (debug build) and RecordMarkSweepCompaction enabled");
505#else
506  MarkSweep::print_new_location_of_heap_address((HeapWord*) old_heap_addr);
507#endif
508}
509
510
511extern "C" methodOop findm(intptr_t pc) {
512  Command c("findm");
513  nmethod* nm = CodeCache::find_nmethod((address)pc);
514  return (nm == NULL) ? (methodOop)NULL : nm->method();
515}
516
517
518extern "C" nmethod* findnm(intptr_t addr) {
519  Command c("findnm");
520  return  CodeCache::find_nmethod((address)addr);
521}
522
523static address same_page(address x, address y) {
524  intptr_t page_bits = -os::vm_page_size();
525  if ((intptr_t(x) & page_bits) == (intptr_t(y) & page_bits)) {
526    return x;
527  } else if (x > y) {
528    return (address)(intptr_t(y) | ~page_bits) + 1;
529  } else {
530    return (address)(intptr_t(y) & page_bits);
531  }
532}
533
534
535static void find(intptr_t x, bool print_pc) {
536  address addr = (address)x;
537
538  CodeBlob* b = CodeCache::find_blob_unsafe(addr);
539  if (b != NULL) {
540    if (b->is_buffer_blob()) {
541      // the interpreter is generated into a buffer blob
542      InterpreterCodelet* i = Interpreter::codelet_containing(addr);
543      if (i != NULL) {
544        i->print();
545        return;
546      }
547      if (Interpreter::contains(addr)) {
548        tty->print_cr(INTPTR_FORMAT " is pointing into interpreter code (not bytecode specific)", addr);
549        return;
550      }
551      //
552      if (AdapterHandlerLibrary::contains(b)) {
553        AdapterHandlerLibrary::print_handler(b);
554      }
555      // the stubroutines are generated into a buffer blob
556      StubCodeDesc* d = StubCodeDesc::desc_for(addr);
557      if (d != NULL) {
558        d->print();
559        if (print_pc) tty->cr();
560        return;
561      }
562      if (StubRoutines::contains(addr)) {
563        tty->print_cr(INTPTR_FORMAT " is pointing to an (unnamed) stub routine", addr);
564        return;
565      }
566      // the InlineCacheBuffer is using stubs generated into a buffer blob
567      if (InlineCacheBuffer::contains(addr)) {
568        tty->print_cr(INTPTR_FORMAT "is pointing into InlineCacheBuffer", addr);
569        return;
570      }
571      VtableStub* v = VtableStubs::stub_containing(addr);
572      if (v != NULL) {
573        v->print();
574        return;
575      }
576    }
577    if (print_pc && b->is_nmethod()) {
578      ResourceMark rm;
579      tty->print("%#p: Compiled ", addr);
580      ((nmethod*)b)->method()->print_value_on(tty);
581      tty->print("  = (CodeBlob*)" INTPTR_FORMAT, b);
582      tty->cr();
583      return;
584    }
585    if ( b->is_nmethod()) {
586      if (b->is_zombie()) {
587        tty->print_cr(INTPTR_FORMAT " is zombie nmethod", b);
588      } else if (b->is_not_entrant()) {
589        tty->print_cr(INTPTR_FORMAT " is non-entrant nmethod", b);
590      }
591    }
592    b->print();
593    return;
594  }
595
596  if (Universe::heap()->is_in_reserved(addr)) {
597    HeapWord* p = Universe::heap()->block_start(addr);
598    bool print = false;
599    // If we couldn't find it it just may mean that heap wasn't parseable
600    // See if we were just given an oop directly
601    if (p != NULL && Universe::heap()->block_is_obj(p)) {
602      print = true;
603    } else if (p == NULL && ((oopDesc*)addr)->is_oop()) {
604      p = (HeapWord*) addr;
605      print = true;
606    }
607    if (print) {
608      oop(p)->print();
609      if (p != (HeapWord*)x && oop(p)->is_constMethod() &&
610          constMethodOop(p)->contains(addr)) {
611        Thread *thread = Thread::current();
612        HandleMark hm(thread);
613        methodHandle mh (thread, constMethodOop(p)->method());
614        if (!mh->is_native()) {
615          tty->print_cr("bci_from(%p) = %d; print_codes():",
616                        addr, mh->bci_from(address(x)));
617          mh->print_codes();
618        }
619      }
620      return;
621    }
622  }
623  if (JNIHandles::is_global_handle((jobject) addr)) {
624    tty->print_cr(INTPTR_FORMAT "is a global jni handle", addr);
625    return;
626  }
627  if (JNIHandles::is_weak_global_handle((jobject) addr)) {
628    tty->print_cr(INTPTR_FORMAT "is a weak global jni handle", addr);
629    return;
630  }
631  if (JNIHandleBlock::any_contains((jobject) addr)) {
632    tty->print_cr(INTPTR_FORMAT "is a local jni handle", addr);
633    return;
634  }
635
636  for(JavaThread *thread = Threads::first(); thread; thread = thread->next()) {
637    // Check for priviledge stack
638    if (thread->privileged_stack_top() != NULL && thread->privileged_stack_top()->contains(addr)) {
639      tty->print_cr(INTPTR_FORMAT "is pointing into the priviledge stack for thread: " INTPTR_FORMAT, addr, thread);
640      return;
641    }
642    // If the addr is a java thread print information about that.
643    if (addr == (address)thread) {
644       thread->print();
645       return;
646    }
647  }
648
649  // Try an OS specific find
650  if (os::find(addr)) {
651    return;
652  }
653
654  if (print_pc) {
655    tty->print_cr(INTPTR_FORMAT ": probably in C++ code; check debugger", addr);
656    Disassembler::decode(same_page(addr-40,addr),same_page(addr+40,addr));
657    return;
658  }
659
660  tty->print_cr(INTPTR_FORMAT "is pointing to unknown location", addr);
661}
662
663
664class LookForRefInGenClosure : public OopsInGenClosure {
665public:
666  oop target;
667  void do_oop(oop* o) {
668    if (o != NULL && *o == target) {
669      tty->print_cr("0x%08x", o);
670    }
671  }
672};
673
674
675class LookForRefInObjectClosure : public ObjectClosure {
676private:
677  LookForRefInGenClosure look_in_object;
678public:
679  LookForRefInObjectClosure(oop target) { look_in_object.target = target; }
680  void do_object(oop obj) {
681    obj->oop_iterate(&look_in_object);
682  }
683};
684
685
686static void findref(intptr_t x) {
687  GenCollectedHeap *gch = GenCollectedHeap::heap();
688  LookForRefInGenClosure lookFor;
689  lookFor.target = (oop) x;
690  LookForRefInObjectClosure look_in_object((oop) x);
691
692  tty->print_cr("Searching heap:");
693  gch->object_iterate(&look_in_object);
694
695  tty->print_cr("Searching strong roots:");
696  Universe::oops_do(&lookFor, false);
697  JNIHandles::oops_do(&lookFor);   // Global (strong) JNI handles
698  Threads::oops_do(&lookFor);
699  ObjectSynchronizer::oops_do(&lookFor);
700  //FlatProfiler::oops_do(&lookFor);
701  SystemDictionary::oops_do(&lookFor);
702
703  tty->print_cr("Done.");
704}
705
706class FindClassObjectClosure: public ObjectClosure {
707  private:
708    const char* _target;
709  public:
710    FindClassObjectClosure(const char name[])  { _target = name; }
711
712    virtual void do_object(oop obj) {
713      if (obj->is_klass()) {
714        Klass* k = klassOop(obj)->klass_part();
715        if (k->name() != NULL) {
716          ResourceMark rm;
717          const char* ext = k->external_name();
718          if ( strcmp(_target, ext) == 0 ) {
719            tty->print_cr("Found " INTPTR_FORMAT, obj);
720            obj->print();
721          }
722        }
723      }
724    }
725};
726
727//
728extern "C" void findclass(const char name[]) {
729  Command c("findclass");
730  if (name != NULL) {
731    tty->print_cr("Finding class %s -> ", name);
732    FindClassObjectClosure srch(name);
733    Universe::heap()->permanent_object_iterate(&srch);
734  }
735}
736
737// Another interface that isn't ambiguous in dbx.
738// Can we someday rename the other find to hsfind?
739extern "C" void hsfind(intptr_t x) {
740  Command c("hsfind");
741  find(x, false);
742}
743
744
745extern "C" void hsfindref(intptr_t x) {
746  Command c("hsfindref");
747  findref(x);
748}
749
750extern "C" void find(intptr_t x) {
751  Command c("find");
752  find(x, false);
753}
754
755
756extern "C" void findpc(intptr_t x) {
757  Command c("findpc");
758  find(x, true);
759}
760
761
762// int versions of all methods to avoid having to type type casts in the debugger
763
764void pp(intptr_t p)          { pp((void*)p); }
765void pp(oop p)               { pp((void*)p); }
766
767void help() {
768  Command c("help");
769  tty->print_cr("basic");
770  tty->print_cr("  pp(void* p)   - try to make sense of p");
771  tty->print_cr("  pv(intptr_t p)- ((PrintableResourceObj*) p)->print()");
772  tty->print_cr("  ps()          - print current thread stack");
773  tty->print_cr("  pss()         - print all thread stacks");
774  tty->print_cr("  pm(int pc)    - print methodOop given compiled PC");
775  tty->print_cr("  findm(intptr_t pc) - finds methodOop");
776  tty->print_cr("  find(intptr_t x)   - finds & prints nmethod/stub/bytecode/oop based on pointer into it");
777
778  tty->print_cr("misc.");
779  tty->print_cr("  flush()       - flushes the log file");
780  tty->print_cr("  events()      - dump last 50 events");
781
782
783  tty->print_cr("compiler debugging");
784  tty->print_cr("  debug()       - to set things up for compiler debugging");
785  tty->print_cr("  ndebug()      - undo debug");
786}
787
788#if 0
789
790// BobV's command parser for debugging on windows when nothing else works.
791
792enum CommandID {
793  CMDID_HELP,
794  CMDID_QUIT,
795  CMDID_HSFIND,
796  CMDID_PSS,
797  CMDID_PS,
798  CMDID_PSF,
799  CMDID_FINDM,
800  CMDID_FINDNM,
801  CMDID_PP,
802  CMDID_BPT,
803  CMDID_EXIT,
804  CMDID_VERIFY,
805  CMDID_THREADS,
806  CMDID_ILLEGAL = 99
807};
808
809struct CommandParser {
810   char *name;
811   CommandID code;
812   char *description;
813};
814
815struct CommandParser CommandList[] = {
816  (char *)"help", CMDID_HELP, "  Dump this list",
817  (char *)"quit", CMDID_QUIT, "  Return from this routine",
818  (char *)"hsfind", CMDID_HSFIND, "Perform an hsfind on an address",
819  (char *)"ps", CMDID_PS, "    Print Current Thread Stack Trace",
820  (char *)"pss", CMDID_PSS, "   Print All Thread Stack Trace",
821  (char *)"psf", CMDID_PSF, "   Print All Stack Frames",
822  (char *)"findm", CMDID_FINDM, " Find a methodOop from a PC",
823  (char *)"findnm", CMDID_FINDNM, "Find an nmethod from a PC",
824  (char *)"pp", CMDID_PP, "    Find out something about a pointer",
825  (char *)"break", CMDID_BPT, " Execute a breakpoint",
826  (char *)"exitvm", CMDID_EXIT, "Exit the VM",
827  (char *)"verify", CMDID_VERIFY, "Perform a Heap Verify",
828  (char *)"thread", CMDID_THREADS, "Dump Info on all Threads",
829  (char *)0, CMDID_ILLEGAL
830};
831
832
833// get_debug_command()
834//
835// Read a command from standard input.
836// This is useful when you have a debugger
837// which doesn't support calling into functions.
838//
839void get_debug_command()
840{
841  ssize_t count;
842  int i,j;
843  bool gotcommand;
844  intptr_t addr;
845  char buffer[256];
846  nmethod *nm;
847  methodOop m;
848
849  tty->print_cr("You have entered the diagnostic command interpreter");
850  tty->print("The supported commands are:\n");
851  for ( i=0; ; i++ ) {
852    if ( CommandList[i].code == CMDID_ILLEGAL )
853      break;
854    tty->print_cr("  %s \n", CommandList[i].name );
855  }
856
857  while ( 1 ) {
858    gotcommand = false;
859    tty->print("Please enter a command: ");
860    count = scanf("%s", buffer) ;
861    if ( count >=0 ) {
862      for ( i=0; ; i++ ) {
863        if ( CommandList[i].code == CMDID_ILLEGAL ) {
864          if (!gotcommand) tty->print("Invalid command, please try again\n");
865          break;
866        }
867        if ( strcmp(buffer, CommandList[i].name) == 0 ) {
868          gotcommand = true;
869          switch ( CommandList[i].code ) {
870              case CMDID_PS:
871                ps();
872                break;
873              case CMDID_PSS:
874                pss();
875                break;
876              case CMDID_PSF:
877                psf();
878                break;
879              case CMDID_FINDM:
880                tty->print("Please enter the hex addr to pass to findm: ");
881                scanf("%I64X", &addr);
882                m = (methodOop)findm(addr);
883                tty->print("findm(0x%I64X) returned 0x%I64X\n", addr, m);
884                break;
885              case CMDID_FINDNM:
886                tty->print("Please enter the hex addr to pass to findnm: ");
887                scanf("%I64X", &addr);
888                nm = (nmethod*)findnm(addr);
889                tty->print("findnm(0x%I64X) returned 0x%I64X\n", addr, nm);
890                break;
891              case CMDID_PP:
892                tty->print("Please enter the hex addr to pass to pp: ");
893                scanf("%I64X", &addr);
894                pp((void*)addr);
895                break;
896              case CMDID_EXIT:
897                exit(0);
898              case CMDID_HELP:
899                tty->print("Here are the supported commands: ");
900                for ( j=0; ; j++ ) {
901                  if ( CommandList[j].code == CMDID_ILLEGAL )
902                    break;
903                  tty->print_cr("  %s --  %s\n", CommandList[j].name,
904                                                 CommandList[j].description );
905                }
906                break;
907              case CMDID_QUIT:
908                return;
909                break;
910              case CMDID_BPT:
911                BREAKPOINT;
912                break;
913              case CMDID_VERIFY:
914                verify();;
915                break;
916              case CMDID_THREADS:
917                threads();;
918                break;
919              case CMDID_HSFIND:
920                tty->print("Please enter the hex addr to pass to hsfind: ");
921                scanf("%I64X", &addr);
922                tty->print("Calling hsfind(0x%I64X)\n", addr);
923                hsfind(addr);
924                break;
925              default:
926              case CMDID_ILLEGAL:
927                break;
928          }
929        }
930      }
931    }
932  }
933}
934#endif
935
936#endif // PRODUCT
937