comparison src/share/vm/utilities/debug.cpp @ 0:a61af66fc99e jdk7-b24

Initial load
author duke
date Sat, 01 Dec 2007 00:00:00 +0000
parents
children ba764ed4b6f2
comparison
equal deleted inserted replaced
-1:000000000000 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
53 void 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
69 static const char* last_file_name = NULL;
70 static 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.
75 bool 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
170 void 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
176 void 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
182 void 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.
193 static jint _exiting_out_of_mem = 0;
194
195 // Just passing the flow to VMError to handle error
196 void 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
214 void 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
223 void 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
230 void 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
237 void 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
244 void 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
250 void 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
272 extern "C" void ps();
273
274 static bool error_reported = false;
275
276 // call this when the VM is dying--it might loosen some asserts
277 void set_error_reported() {
278 error_reported = true;
279 }
280
281 bool 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
292 class 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
311 int Command::level = 0;
312
313 extern "C" void blob(CodeBlob* cb) {
314 Command c("blob");
315 cb->print();
316 }
317
318
319 extern "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
326 extern "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
338 extern "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
346 extern "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
358 extern "C" void universe() {
359 Command c("universe");
360 Universe::print();
361 }
362
363
364 extern "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
381 extern "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
394 extern "C" void pa(intptr_t p) { ((AllocatedObj*) p)->print(); }
395 extern "C" void findpc(intptr_t x);
396
397 extern "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
423 extern "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
437 extern "C" void threads() {
438 Command c("threads");
439 Threads::print(false, true);
440 }
441
442
443 extern "C" void psd() {
444 Command c("psd");
445 SystemDictionary::print();
446 }
447
448
449 extern "C" void safepoints() {
450 Command c("safepoints");
451 SafepointSynchronize::print_state();
452 }
453
454
455 extern "C" void pss() { // print all stacks
456 Command c("pss");
457 Threads::print(true, true);
458 }
459
460
461 extern "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
470 extern "C" void ndebug() { // undo debug()
471 Command c("ndebug");
472 PrintCompilation = false;
473 PrintInlining = PrintAssembly = false;
474 tty->flush();
475 }
476
477
478 extern "C" void flush() {
479 Command c("flush");
480 tty->flush();
481 }
482
483
484 extern "C" void events() {
485 Command c("events");
486 Events::print_last(tty, 50);
487 }
488
489
490 extern "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.
500 extern "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
511 extern "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
518 extern "C" nmethod* findnm(intptr_t addr) {
519 Command c("findnm");
520 return CodeCache::find_nmethod((address)addr);
521 }
522
523 static 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
535 static 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
664 class LookForRefInGenClosure : public OopsInGenClosure {
665 public:
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
675 class LookForRefInObjectClosure : public ObjectClosure {
676 private:
677 LookForRefInGenClosure look_in_object;
678 public:
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
686 static 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
706 class 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 //
728 extern "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?
739 extern "C" void hsfind(intptr_t x) {
740 Command c("hsfind");
741 find(x, false);
742 }
743
744
745 extern "C" void hsfindref(intptr_t x) {
746 Command c("hsfindref");
747 findref(x);
748 }
749
750 extern "C" void find(intptr_t x) {
751 Command c("find");
752 find(x, false);
753 }
754
755
756 extern "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
764 void pp(intptr_t p) { pp((void*)p); }
765 void pp(oop p) { pp((void*)p); }
766
767 void 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
792 enum 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
809 struct CommandParser {
810 char *name;
811 CommandID code;
812 char *description;
813 };
814
815 struct 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 //
839 void 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