debug.cpp revision 356:1ee8caae33af
1/*
2 * Copyright 1997-2008 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
212  // Dump core and abort
213  vm_abort(true);
214}
215
216void report_vm_out_of_memory_vararg(const char* file_name, int line_no, size_t size, const char* format, ...) {
217  char buffer[256];
218  va_list ap;
219  va_start(ap, format);
220  jio_vsnprintf(buffer, sizeof(buffer), format, ap);
221  va_end(ap);
222  report_vm_out_of_memory(file_name, line_no, size, buffer);
223}
224
225void report_should_not_call(const char* file_name, int line_no) {
226  if (Debugging || assert_is_suppressed(file_name, line_no))  return;
227  VMError err(ThreadLocalStorage::get_thread_slow(), "ShouldNotCall()", file_name, line_no);
228  err.report_and_die();
229}
230
231
232void report_should_not_reach_here(const char* file_name, int line_no) {
233  if (Debugging || assert_is_suppressed(file_name, line_no))  return;
234  VMError err(ThreadLocalStorage::get_thread_slow(), "ShouldNotReachHere()", file_name, line_no);
235  err.report_and_die();
236}
237
238
239void report_unimplemented(const char* file_name, int line_no) {
240  if (Debugging || assert_is_suppressed(file_name, line_no))  return;
241  VMError err(ThreadLocalStorage::get_thread_slow(), "Unimplemented()", file_name, line_no);
242  err.report_and_die();
243}
244
245
246void report_untested(const char* file_name, int line_no, const char* msg) {
247#ifndef PRODUCT
248  warning("Untested: %s in %s: %d\n", msg, file_name, line_no);
249#endif // PRODUCT
250}
251
252void report_java_out_of_memory(const char* message) {
253  static jint out_of_memory_reported = 0;
254
255  // A number of threads may attempt to report OutOfMemoryError at around the
256  // same time. To avoid dumping the heap or executing the data collection
257  // commands multiple times we just do it once when the first threads reports
258  // the error.
259  if (Atomic::cmpxchg(1, &out_of_memory_reported, 0) == 0) {
260    // create heap dump before OnOutOfMemoryError commands are executed
261    if (HeapDumpOnOutOfMemoryError) {
262      tty->print_cr("java.lang.OutOfMemoryError: %s", message);
263      HeapDumper::dump_heap();
264    }
265
266    if (OnOutOfMemoryError && OnOutOfMemoryError[0]) {
267      VMError err(message);
268      err.report_java_out_of_memory();
269    }
270  }
271}
272
273
274extern "C" void ps();
275
276static bool error_reported = false;
277
278// call this when the VM is dying--it might loosen some asserts
279void set_error_reported() {
280  error_reported = true;
281}
282
283bool is_error_reported() {
284    return error_reported;
285}
286
287// ------ helper functions for debugging go here ------------
288
289#ifndef PRODUCT
290// All debug entries should be wrapped with a stack allocated
291// Command object. It makes sure a resource mark is set and
292// flushes the logfile to prevent file sharing problems.
293
294class Command : public StackObj {
295 private:
296  ResourceMark rm;
297  ResetNoHandleMark rnhm;
298  HandleMark   hm;
299  bool debug_save;
300 public:
301  static int level;
302  Command(const char* str) {
303    debug_save = Debugging;
304    Debugging = true;
305    if (level++ > 0)  return;
306    tty->cr();
307    tty->print_cr("\"Executing %s\"", str);
308  }
309
310  ~Command() { tty->flush(); Debugging = debug_save; level--; }
311};
312
313int Command::level = 0;
314
315extern "C" void blob(CodeBlob* cb) {
316  Command c("blob");
317  cb->print();
318}
319
320
321extern "C" void dump_vtable(address p) {
322  Command c("dump_vtable");
323  klassOop k = (klassOop)p;
324  instanceKlass::cast(k)->vtable()->print();
325}
326
327
328extern "C" void nm(intptr_t p) {
329  // Actually we look through all CodeBlobs (the nm name has been kept for backwards compatability)
330  Command c("nm");
331  CodeBlob* cb = CodeCache::find_blob((address)p);
332  if (cb == NULL) {
333    tty->print_cr("NULL");
334  } else {
335    cb->print();
336  }
337}
338
339
340extern "C" void disnm(intptr_t p) {
341  Command c("disnm");
342  CodeBlob* cb = CodeCache::find_blob((address) p);
343  cb->print();
344  Disassembler::decode(cb);
345}
346
347
348extern "C" void printnm(intptr_t p) {
349  char buffer[256];
350  sprintf(buffer, "printnm: " INTPTR_FORMAT, p);
351  Command c(buffer);
352  CodeBlob* cb = CodeCache::find_blob((address) p);
353  if (cb->is_nmethod()) {
354    nmethod* nm = (nmethod*)cb;
355    nm->print_nmethod(true);
356  }
357}
358
359
360extern "C" void universe() {
361  Command c("universe");
362  Universe::print();
363}
364
365
366extern "C" void verify() {
367  // try to run a verify on the entire system
368  // note: this may not be safe if we're not at a safepoint; for debugging,
369  // this manipulates the safepoint settings to avoid assertion failures
370  Command c("universe verify");
371  bool safe = SafepointSynchronize::is_at_safepoint();
372  if (!safe) {
373    tty->print_cr("warning: not at safepoint -- verify may fail");
374    SafepointSynchronize::set_is_at_safepoint();
375  }
376  // Ensure Eden top is correct before verification
377  Universe::heap()->prepare_for_verify();
378  Universe::verify(true);
379  if (!safe) SafepointSynchronize::set_is_not_at_safepoint();
380}
381
382
383extern "C" void pp(void* p) {
384  Command c("pp");
385  FlagSetting fl(PrintVMMessages, true);
386  if (Universe::heap()->is_in(p)) {
387    oop obj = oop(p);
388    obj->print();
389  } else {
390    tty->print("%#p", p);
391  }
392}
393
394
395// pv: print vm-printable object
396extern "C" void pa(intptr_t p)   { ((AllocatedObj*) p)->print(); }
397extern "C" void findpc(intptr_t x);
398
399extern "C" void ps() { // print stack
400  Command c("ps");
401
402
403  // Prints the stack of the current Java thread
404  JavaThread* p = JavaThread::active();
405  tty->print(" for thread: ");
406  p->print();
407  tty->cr();
408
409  if (p->has_last_Java_frame()) {
410    // If the last_Java_fp is set we are in C land and
411    // can call the standard stack_trace function.
412    p->trace_stack();
413  } else {
414    frame f = os::current_frame();
415    RegisterMap reg_map(p);
416    f = f.sender(&reg_map);
417    tty->print("(guessing starting frame id=%#p based on current fp)\n", f.id());
418    p->trace_stack_from(vframe::new_vframe(&f, &reg_map, p));
419  pd_ps(f);
420  }
421
422}
423
424
425extern "C" void psf() { // print stack frames
426  {
427    Command c("psf");
428    JavaThread* p = JavaThread::active();
429    tty->print(" for thread: ");
430    p->print();
431    tty->cr();
432    if (p->has_last_Java_frame()) {
433      p->trace_frames();
434    }
435  }
436}
437
438
439extern "C" void threads() {
440  Command c("threads");
441  Threads::print(false, true);
442}
443
444
445extern "C" void psd() {
446  Command c("psd");
447  SystemDictionary::print();
448}
449
450
451extern "C" void safepoints() {
452  Command c("safepoints");
453  SafepointSynchronize::print_state();
454}
455
456
457extern "C" void pss() { // print all stacks
458  Command c("pss");
459  Threads::print(true, true);
460}
461
462
463extern "C" void debug() {               // to set things up for compiler debugging
464  Command c("debug");
465  WizardMode = true;
466  PrintVMMessages = PrintCompilation = true;
467  PrintInlining = PrintAssembly = true;
468  tty->flush();
469}
470
471
472extern "C" void ndebug() {              // undo debug()
473  Command c("ndebug");
474  PrintCompilation = false;
475  PrintInlining = PrintAssembly = false;
476  tty->flush();
477}
478
479
480extern "C" void flush()  {
481  Command c("flush");
482  tty->flush();
483}
484
485
486extern "C" void events() {
487  Command c("events");
488  Events::print_last(tty, 50);
489}
490
491
492extern "C" void nevents(int n) {
493  Command c("events");
494  Events::print_last(tty, n);
495}
496
497
498// Given a heap address that was valid before the most recent GC, if
499// the oop that used to contain it is still live, prints the new
500// location of the oop and the address. Useful for tracking down
501// certain kinds of naked oop and oop map bugs.
502extern "C" void pnl(intptr_t old_heap_addr) {
503  // Print New Location of old heap address
504  Command c("pnl");
505#ifndef VALIDATE_MARK_SWEEP
506  tty->print_cr("Requires build with VALIDATE_MARK_SWEEP defined (debug build) and RecordMarkSweepCompaction enabled");
507#else
508  MarkSweep::print_new_location_of_heap_address((HeapWord*) old_heap_addr);
509#endif
510}
511
512
513extern "C" methodOop findm(intptr_t pc) {
514  Command c("findm");
515  nmethod* nm = CodeCache::find_nmethod((address)pc);
516  return (nm == NULL) ? (methodOop)NULL : nm->method();
517}
518
519
520extern "C" nmethod* findnm(intptr_t addr) {
521  Command c("findnm");
522  return  CodeCache::find_nmethod((address)addr);
523}
524
525static address same_page(address x, address y) {
526  intptr_t page_bits = -os::vm_page_size();
527  if ((intptr_t(x) & page_bits) == (intptr_t(y) & page_bits)) {
528    return x;
529  } else if (x > y) {
530    return (address)(intptr_t(y) | ~page_bits) + 1;
531  } else {
532    return (address)(intptr_t(y) & page_bits);
533  }
534}
535
536
537static void find(intptr_t x, bool print_pc) {
538  address addr = (address)x;
539
540  CodeBlob* b = CodeCache::find_blob_unsafe(addr);
541  if (b != NULL) {
542    if (b->is_buffer_blob()) {
543      // the interpreter is generated into a buffer blob
544      InterpreterCodelet* i = Interpreter::codelet_containing(addr);
545      if (i != NULL) {
546        i->print();
547        return;
548      }
549      if (Interpreter::contains(addr)) {
550        tty->print_cr(INTPTR_FORMAT " is pointing into interpreter code (not bytecode specific)", addr);
551        return;
552      }
553      //
554      if (AdapterHandlerLibrary::contains(b)) {
555        AdapterHandlerLibrary::print_handler(b);
556      }
557      // the stubroutines are generated into a buffer blob
558      StubCodeDesc* d = StubCodeDesc::desc_for(addr);
559      if (d != NULL) {
560        d->print();
561        if (print_pc) tty->cr();
562        return;
563      }
564      if (StubRoutines::contains(addr)) {
565        tty->print_cr(INTPTR_FORMAT " is pointing to an (unnamed) stub routine", addr);
566        return;
567      }
568      // the InlineCacheBuffer is using stubs generated into a buffer blob
569      if (InlineCacheBuffer::contains(addr)) {
570        tty->print_cr(INTPTR_FORMAT "is pointing into InlineCacheBuffer", addr);
571        return;
572      }
573      VtableStub* v = VtableStubs::stub_containing(addr);
574      if (v != NULL) {
575        v->print();
576        return;
577      }
578    }
579    if (print_pc && b->is_nmethod()) {
580      ResourceMark rm;
581      tty->print("%#p: Compiled ", addr);
582      ((nmethod*)b)->method()->print_value_on(tty);
583      tty->print("  = (CodeBlob*)" INTPTR_FORMAT, b);
584      tty->cr();
585      return;
586    }
587    if ( b->is_nmethod()) {
588      if (b->is_zombie()) {
589        tty->print_cr(INTPTR_FORMAT " is zombie nmethod", b);
590      } else if (b->is_not_entrant()) {
591        tty->print_cr(INTPTR_FORMAT " is non-entrant nmethod", b);
592      }
593    }
594    b->print();
595    return;
596  }
597
598  if (Universe::heap()->is_in_reserved(addr)) {
599    HeapWord* p = Universe::heap()->block_start(addr);
600    bool print = false;
601    // If we couldn't find it it just may mean that heap wasn't parseable
602    // See if we were just given an oop directly
603    if (p != NULL && Universe::heap()->block_is_obj(p)) {
604      print = true;
605    } else if (p == NULL && ((oopDesc*)addr)->is_oop()) {
606      p = (HeapWord*) addr;
607      print = true;
608    }
609    if (print) {
610      oop(p)->print();
611      if (p != (HeapWord*)x && oop(p)->is_constMethod() &&
612          constMethodOop(p)->contains(addr)) {
613        Thread *thread = Thread::current();
614        HandleMark hm(thread);
615        methodHandle mh (thread, constMethodOop(p)->method());
616        if (!mh->is_native()) {
617          tty->print_cr("bci_from(%p) = %d; print_codes():",
618                        addr, mh->bci_from(address(x)));
619          mh->print_codes();
620        }
621      }
622      return;
623    }
624  }
625  if (JNIHandles::is_global_handle((jobject) addr)) {
626    tty->print_cr(INTPTR_FORMAT "is a global jni handle", addr);
627    return;
628  }
629  if (JNIHandles::is_weak_global_handle((jobject) addr)) {
630    tty->print_cr(INTPTR_FORMAT "is a weak global jni handle", addr);
631    return;
632  }
633  if (JNIHandleBlock::any_contains((jobject) addr)) {
634    tty->print_cr(INTPTR_FORMAT "is a local jni handle", addr);
635    return;
636  }
637
638  for(JavaThread *thread = Threads::first(); thread; thread = thread->next()) {
639    // Check for priviledge stack
640    if (thread->privileged_stack_top() != NULL && thread->privileged_stack_top()->contains(addr)) {
641      tty->print_cr(INTPTR_FORMAT "is pointing into the priviledge stack for thread: " INTPTR_FORMAT, addr, thread);
642      return;
643    }
644    // If the addr is a java thread print information about that.
645    if (addr == (address)thread) {
646       thread->print();
647       return;
648    }
649  }
650
651  // Try an OS specific find
652  if (os::find(addr)) {
653    return;
654  }
655
656  if (print_pc) {
657    tty->print_cr(INTPTR_FORMAT ": probably in C++ code; check debugger", addr);
658    Disassembler::decode(same_page(addr-40,addr),same_page(addr+40,addr));
659    return;
660  }
661
662  tty->print_cr(INTPTR_FORMAT "is pointing to unknown location", addr);
663}
664
665
666class LookForRefInGenClosure : public OopsInGenClosure {
667public:
668  oop target;
669  void do_oop(oop* o) {
670    if (o != NULL && *o == target) {
671      tty->print_cr(INTPTR_FORMAT, o);
672    }
673  }
674  void do_oop(narrowOop* o) { ShouldNotReachHere(); }
675};
676
677
678class LookForRefInObjectClosure : public ObjectClosure {
679private:
680  LookForRefInGenClosure look_in_object;
681public:
682  LookForRefInObjectClosure(oop target) { look_in_object.target = target; }
683  void do_object(oop obj) {
684    obj->oop_iterate(&look_in_object);
685  }
686};
687
688
689static void findref(intptr_t x) {
690  CollectedHeap *ch = Universe::heap();
691  LookForRefInGenClosure lookFor;
692  lookFor.target = (oop) x;
693  LookForRefInObjectClosure look_in_object((oop) x);
694
695  tty->print_cr("Searching heap:");
696  ch->object_iterate(&look_in_object);
697
698  tty->print_cr("Searching strong roots:");
699  Universe::oops_do(&lookFor, false);
700  JNIHandles::oops_do(&lookFor);   // Global (strong) JNI handles
701  Threads::oops_do(&lookFor);
702  ObjectSynchronizer::oops_do(&lookFor);
703  //FlatProfiler::oops_do(&lookFor);
704  SystemDictionary::oops_do(&lookFor);
705
706  tty->print_cr("Done.");
707}
708
709class FindClassObjectClosure: public ObjectClosure {
710  private:
711    const char* _target;
712  public:
713    FindClassObjectClosure(const char name[])  { _target = name; }
714
715    virtual void do_object(oop obj) {
716      if (obj->is_klass()) {
717        Klass* k = klassOop(obj)->klass_part();
718        if (k->name() != NULL) {
719          ResourceMark rm;
720          const char* ext = k->external_name();
721          if ( strcmp(_target, ext) == 0 ) {
722            tty->print_cr("Found " INTPTR_FORMAT, obj);
723            obj->print();
724          }
725        }
726      }
727    }
728};
729
730//
731extern "C" void findclass(const char name[]) {
732  Command c("findclass");
733  if (name != NULL) {
734    tty->print_cr("Finding class %s -> ", name);
735    FindClassObjectClosure srch(name);
736    Universe::heap()->permanent_object_iterate(&srch);
737  }
738}
739
740// Another interface that isn't ambiguous in dbx.
741// Can we someday rename the other find to hsfind?
742extern "C" void hsfind(intptr_t x) {
743  Command c("hsfind");
744  find(x, false);
745}
746
747
748extern "C" void hsfindref(intptr_t x) {
749  Command c("hsfindref");
750  findref(x);
751}
752
753extern "C" void find(intptr_t x) {
754  Command c("find");
755  find(x, false);
756}
757
758
759extern "C" void findpc(intptr_t x) {
760  Command c("findpc");
761  find(x, true);
762}
763
764
765// int versions of all methods to avoid having to type type casts in the debugger
766
767void pp(intptr_t p)          { pp((void*)p); }
768void pp(oop p)               { pp((void*)p); }
769
770void help() {
771  Command c("help");
772  tty->print_cr("basic");
773  tty->print_cr("  pp(void* p)   - try to make sense of p");
774  tty->print_cr("  pv(intptr_t p)- ((PrintableResourceObj*) p)->print()");
775  tty->print_cr("  ps()          - print current thread stack");
776  tty->print_cr("  pss()         - print all thread stacks");
777  tty->print_cr("  pm(int pc)    - print methodOop given compiled PC");
778  tty->print_cr("  findm(intptr_t pc) - finds methodOop");
779  tty->print_cr("  find(intptr_t x)   - finds & prints nmethod/stub/bytecode/oop based on pointer into it");
780
781  tty->print_cr("misc.");
782  tty->print_cr("  flush()       - flushes the log file");
783  tty->print_cr("  events()      - dump last 50 events");
784
785
786  tty->print_cr("compiler debugging");
787  tty->print_cr("  debug()       - to set things up for compiler debugging");
788  tty->print_cr("  ndebug()      - undo debug");
789}
790
791#if 0
792
793// BobV's command parser for debugging on windows when nothing else works.
794
795enum CommandID {
796  CMDID_HELP,
797  CMDID_QUIT,
798  CMDID_HSFIND,
799  CMDID_PSS,
800  CMDID_PS,
801  CMDID_PSF,
802  CMDID_FINDM,
803  CMDID_FINDNM,
804  CMDID_PP,
805  CMDID_BPT,
806  CMDID_EXIT,
807  CMDID_VERIFY,
808  CMDID_THREADS,
809  CMDID_ILLEGAL = 99
810};
811
812struct CommandParser {
813   char *name;
814   CommandID code;
815   char *description;
816};
817
818struct CommandParser CommandList[] = {
819  (char *)"help", CMDID_HELP, "  Dump this list",
820  (char *)"quit", CMDID_QUIT, "  Return from this routine",
821  (char *)"hsfind", CMDID_HSFIND, "Perform an hsfind on an address",
822  (char *)"ps", CMDID_PS, "    Print Current Thread Stack Trace",
823  (char *)"pss", CMDID_PSS, "   Print All Thread Stack Trace",
824  (char *)"psf", CMDID_PSF, "   Print All Stack Frames",
825  (char *)"findm", CMDID_FINDM, " Find a methodOop from a PC",
826  (char *)"findnm", CMDID_FINDNM, "Find an nmethod from a PC",
827  (char *)"pp", CMDID_PP, "    Find out something about a pointer",
828  (char *)"break", CMDID_BPT, " Execute a breakpoint",
829  (char *)"exitvm", CMDID_EXIT, "Exit the VM",
830  (char *)"verify", CMDID_VERIFY, "Perform a Heap Verify",
831  (char *)"thread", CMDID_THREADS, "Dump Info on all Threads",
832  (char *)0, CMDID_ILLEGAL
833};
834
835
836// get_debug_command()
837//
838// Read a command from standard input.
839// This is useful when you have a debugger
840// which doesn't support calling into functions.
841//
842void get_debug_command()
843{
844  ssize_t count;
845  int i,j;
846  bool gotcommand;
847  intptr_t addr;
848  char buffer[256];
849  nmethod *nm;
850  methodOop m;
851
852  tty->print_cr("You have entered the diagnostic command interpreter");
853  tty->print("The supported commands are:\n");
854  for ( i=0; ; i++ ) {
855    if ( CommandList[i].code == CMDID_ILLEGAL )
856      break;
857    tty->print_cr("  %s \n", CommandList[i].name );
858  }
859
860  while ( 1 ) {
861    gotcommand = false;
862    tty->print("Please enter a command: ");
863    count = scanf("%s", buffer) ;
864    if ( count >=0 ) {
865      for ( i=0; ; i++ ) {
866        if ( CommandList[i].code == CMDID_ILLEGAL ) {
867          if (!gotcommand) tty->print("Invalid command, please try again\n");
868          break;
869        }
870        if ( strcmp(buffer, CommandList[i].name) == 0 ) {
871          gotcommand = true;
872          switch ( CommandList[i].code ) {
873              case CMDID_PS:
874                ps();
875                break;
876              case CMDID_PSS:
877                pss();
878                break;
879              case CMDID_PSF:
880                psf();
881                break;
882              case CMDID_FINDM:
883                tty->print("Please enter the hex addr to pass to findm: ");
884                scanf("%I64X", &addr);
885                m = (methodOop)findm(addr);
886                tty->print("findm(0x%I64X) returned 0x%I64X\n", addr, m);
887                break;
888              case CMDID_FINDNM:
889                tty->print("Please enter the hex addr to pass to findnm: ");
890                scanf("%I64X", &addr);
891                nm = (nmethod*)findnm(addr);
892                tty->print("findnm(0x%I64X) returned 0x%I64X\n", addr, nm);
893                break;
894              case CMDID_PP:
895                tty->print("Please enter the hex addr to pass to pp: ");
896                scanf("%I64X", &addr);
897                pp((void*)addr);
898                break;
899              case CMDID_EXIT:
900                exit(0);
901              case CMDID_HELP:
902                tty->print("Here are the supported commands: ");
903                for ( j=0; ; j++ ) {
904                  if ( CommandList[j].code == CMDID_ILLEGAL )
905                    break;
906                  tty->print_cr("  %s --  %s\n", CommandList[j].name,
907                                                 CommandList[j].description );
908                }
909                break;
910              case CMDID_QUIT:
911                return;
912                break;
913              case CMDID_BPT:
914                BREAKPOINT;
915                break;
916              case CMDID_VERIFY:
917                verify();;
918                break;
919              case CMDID_THREADS:
920                threads();;
921                break;
922              case CMDID_HSFIND:
923                tty->print("Please enter the hex addr to pass to hsfind: ");
924                scanf("%I64X", &addr);
925                tty->print("Calling hsfind(0x%I64X)\n", addr);
926                hsfind(addr);
927                break;
928              default:
929              case CMDID_ILLEGAL:
930                break;
931          }
932        }
933      }
934    }
935  }
936}
937#endif
938
939#endif // PRODUCT
940