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