Thu, 31 Mar 2011 16:54:27 -0700
7032849: 7022998 changes broke hs_err compile task print
Summary: Initialize the time stamp on ostream used for hs_err dumping.
Reviewed-by: never
1 /*
2 * Copyright (c) 1997, 2010, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
25 #include "precompiled.hpp"
26 #include "classfile/systemDictionary.hpp"
27 #include "code/codeCache.hpp"
28 #include "code/icBuffer.hpp"
29 #include "code/nmethod.hpp"
30 #include "code/vtableStubs.hpp"
31 #include "compiler/compileBroker.hpp"
32 #include "compiler/disassembler.hpp"
33 #include "gc_implementation/shared/markSweep.hpp"
34 #include "gc_interface/collectedHeap.hpp"
35 #include "interpreter/bytecodeHistogram.hpp"
36 #include "interpreter/interpreter.hpp"
37 #include "memory/resourceArea.hpp"
38 #include "memory/universe.hpp"
39 #include "oops/oop.inline.hpp"
40 #include "prims/privilegedStack.hpp"
41 #include "runtime/arguments.hpp"
42 #include "runtime/frame.hpp"
43 #include "runtime/java.hpp"
44 #include "runtime/sharedRuntime.hpp"
45 #include "runtime/stubCodeGenerator.hpp"
46 #include "runtime/stubRoutines.hpp"
47 #include "runtime/vframe.hpp"
48 #include "services/heapDumper.hpp"
49 #include "utilities/defaultStream.hpp"
50 #include "utilities/events.hpp"
51 #include "utilities/top.hpp"
52 #include "utilities/vmError.hpp"
53 #ifdef TARGET_OS_FAMILY_linux
54 # include "os_linux.inline.hpp"
55 # include "thread_linux.inline.hpp"
56 #endif
57 #ifdef TARGET_OS_FAMILY_solaris
58 # include "os_solaris.inline.hpp"
59 # include "thread_solaris.inline.hpp"
60 #endif
61 #ifdef TARGET_OS_FAMILY_windows
62 # include "os_windows.inline.hpp"
63 # include "thread_windows.inline.hpp"
64 #endif
66 #ifndef ASSERT
67 # ifdef _DEBUG
68 // NOTE: don't turn the lines below into a comment -- if you're getting
69 // a compile error here, change the settings to define ASSERT
70 ASSERT should be defined when _DEBUG is defined. It is not intended to be used for debugging
71 functions that do not slow down the system too much and thus can be left in optimized code.
72 On the other hand, the code should not be included in a production version.
73 # endif // _DEBUG
74 #endif // ASSERT
77 #ifdef _DEBUG
78 # ifndef ASSERT
79 configuration error: ASSERT must be defined in debug version
80 # endif // ASSERT
81 #endif // _DEBUG
84 #ifdef PRODUCT
85 # if -defined _DEBUG || -defined ASSERT
86 configuration error: ASSERT et al. must not be defined in PRODUCT version
87 # endif
88 #endif // PRODUCT
91 void warning(const char* format, ...) {
92 if (PrintWarnings) {
93 // In case error happens before init or during shutdown
94 if (tty == NULL) ostream_init();
96 tty->print("%s warning: ", VM_Version::vm_name());
97 va_list ap;
98 va_start(ap, format);
99 tty->vprint_cr(format, ap);
100 va_end(ap);
101 }
102 if (BreakAtWarning) BREAKPOINT;
103 }
105 #ifndef PRODUCT
107 #define is_token_break(ch) (isspace(ch) || (ch) == ',')
109 static const char* last_file_name = NULL;
110 static int last_line_no = -1;
112 // assert/guarantee/... may happen very early during VM initialization.
113 // Don't rely on anything that is initialized by Threads::create_vm(). For
114 // example, don't use tty.
115 bool error_is_suppressed(const char* file_name, int line_no) {
116 // The following 1-element cache requires that passed-in
117 // file names are always only constant literals.
118 if (file_name == last_file_name && line_no == last_line_no) return true;
120 int file_name_len = (int)strlen(file_name);
121 char separator = os::file_separator()[0];
122 const char* base_name = strrchr(file_name, separator);
123 if (base_name == NULL)
124 base_name = file_name;
126 // scan the SuppressErrorAt option
127 const char* cp = SuppressErrorAt;
128 for (;;) {
129 const char* sfile;
130 int sfile_len;
131 int sline;
132 bool noisy;
133 while ((*cp) != '\0' && is_token_break(*cp)) cp++;
134 if ((*cp) == '\0') break;
135 sfile = cp;
136 while ((*cp) != '\0' && !is_token_break(*cp) && (*cp) != ':') cp++;
137 sfile_len = cp - sfile;
138 if ((*cp) == ':') cp++;
139 sline = 0;
140 while ((*cp) != '\0' && isdigit(*cp)) {
141 sline *= 10;
142 sline += (*cp) - '0';
143 cp++;
144 }
145 // "file:line!" means the assert suppression is not silent
146 noisy = ((*cp) == '!');
147 while ((*cp) != '\0' && !is_token_break(*cp)) cp++;
148 // match the line
149 if (sline != 0) {
150 if (sline != line_no) continue;
151 }
152 // match the file
153 if (sfile_len > 0) {
154 const char* look = file_name;
155 const char* look_max = file_name + file_name_len - sfile_len;
156 const char* foundp;
157 bool match = false;
158 while (!match
159 && (foundp = strchr(look, sfile[0])) != NULL
160 && foundp <= look_max) {
161 match = true;
162 for (int i = 1; i < sfile_len; i++) {
163 if (sfile[i] != foundp[i]) {
164 match = false;
165 break;
166 }
167 }
168 look = foundp + 1;
169 }
170 if (!match) continue;
171 }
172 // got a match!
173 if (noisy) {
174 fdStream out(defaultStream::output_fd());
175 out.print_raw("[error suppressed at ");
176 out.print_raw(base_name);
177 char buf[16];
178 jio_snprintf(buf, sizeof(buf), ":%d]", line_no);
179 out.print_raw_cr(buf);
180 } else {
181 // update 1-element cache for fast silent matches
182 last_file_name = file_name;
183 last_line_no = line_no;
184 }
185 return true;
186 }
188 if (!is_error_reported()) {
189 // print a friendly hint:
190 fdStream out(defaultStream::output_fd());
191 out.print_raw_cr("# To suppress the following error report, specify this argument");
192 out.print_raw ("# after -XX: or in .hotspotrc: SuppressErrorAt=");
193 out.print_raw (base_name);
194 char buf[16];
195 jio_snprintf(buf, sizeof(buf), ":%d", line_no);
196 out.print_raw_cr(buf);
197 }
198 return false;
199 }
201 #undef is_token_break
203 #else
205 // Place-holder for non-existent suppression check:
206 #define error_is_suppressed(file_name, line_no) (false)
208 #endif //PRODUCT
210 void report_vm_error(const char* file, int line, const char* error_msg,
211 const char* detail_msg)
212 {
213 if (Debugging || error_is_suppressed(file, line)) return;
214 Thread* const thread = ThreadLocalStorage::get_thread_slow();
215 VMError err(thread, file, line, error_msg, detail_msg);
216 err.report_and_die();
217 }
219 void report_fatal(const char* file, int line, const char* message)
220 {
221 report_vm_error(file, line, "fatal error", message);
222 }
224 // Used by report_vm_out_of_memory to detect recursion.
225 static jint _exiting_out_of_mem = 0;
227 void report_vm_out_of_memory(const char* file, int line, size_t size,
228 const char* message) {
229 if (Debugging) return;
231 // We try to gather additional information for the first out of memory
232 // error only; gathering additional data might cause an allocation and a
233 // recursive out_of_memory condition.
235 const jint exiting = 1;
236 // If we succeed in changing the value, we're the first one in.
237 bool first_time_here = Atomic::xchg(exiting, &_exiting_out_of_mem) != exiting;
239 if (first_time_here) {
240 Thread* thread = ThreadLocalStorage::get_thread_slow();
241 VMError(thread, file, line, size, message).report_and_die();
242 }
244 // Dump core and abort
245 vm_abort(true);
246 }
248 void report_should_not_call(const char* file, int line) {
249 report_vm_error(file, line, "ShouldNotCall()");
250 }
252 void report_should_not_reach_here(const char* file, int line) {
253 report_vm_error(file, line, "ShouldNotReachHere()");
254 }
256 void report_unimplemented(const char* file, int line) {
257 report_vm_error(file, line, "Unimplemented()");
258 }
260 void report_untested(const char* file, int line, const char* message) {
261 #ifndef PRODUCT
262 warning("Untested: %s in %s: %d\n", message, file, line);
263 #endif // PRODUCT
264 }
266 void report_out_of_shared_space(SharedSpaceType shared_space) {
267 static const char* name[] = {
268 "permanent generation",
269 "shared read only space",
270 "shared read write space",
271 "shared miscellaneous data space"
272 };
273 static const char* flag[] = {
274 "PermGen",
275 "SharedReadOnlySize",
276 "SharedReadWriteSize",
277 "SharedMiscDataSize"
278 };
280 warning("\nThe %s is not large enough\n"
281 "to preload requested classes. Use -XX:%s=\n"
282 "to increase the initial size of %s.\n",
283 name[shared_space], flag[shared_space], name[shared_space]);
284 exit(2);
285 }
287 void report_java_out_of_memory(const char* message) {
288 static jint out_of_memory_reported = 0;
290 // A number of threads may attempt to report OutOfMemoryError at around the
291 // same time. To avoid dumping the heap or executing the data collection
292 // commands multiple times we just do it once when the first threads reports
293 // the error.
294 if (Atomic::cmpxchg(1, &out_of_memory_reported, 0) == 0) {
295 // create heap dump before OnOutOfMemoryError commands are executed
296 if (HeapDumpOnOutOfMemoryError) {
297 tty->print_cr("java.lang.OutOfMemoryError: %s", message);
298 HeapDumper::dump_heap_from_oome();
299 }
301 if (OnOutOfMemoryError && OnOutOfMemoryError[0]) {
302 VMError err(message);
303 err.report_java_out_of_memory();
304 }
305 }
306 }
309 extern "C" void ps();
311 static bool error_reported = false;
313 // call this when the VM is dying--it might loosen some asserts
314 void set_error_reported() {
315 error_reported = true;
316 }
318 bool is_error_reported() {
319 return error_reported;
320 }
322 #ifndef PRODUCT
323 #include <signal.h>
325 void test_error_handler(size_t test_num)
326 {
327 if (test_num == 0) return;
329 // If asserts are disabled, use the corresponding guarantee instead.
330 size_t n = test_num;
331 NOT_DEBUG(if (n <= 2) n += 2);
333 const char* const str = "hello";
334 const size_t num = (size_t)os::vm_page_size();
336 const char* const eol = os::line_separator();
337 const char* const msg = "this message should be truncated during formatting";
339 // Keep this in sync with test/runtime/6888954/vmerrors.sh.
340 switch (n) {
341 case 1: assert(str == NULL, "expected null");
342 case 2: assert(num == 1023 && *str == 'X',
343 err_msg("num=" SIZE_FORMAT " str=\"%s\"", num, str));
344 case 3: guarantee(str == NULL, "expected null");
345 case 4: guarantee(num == 1023 && *str == 'X',
346 err_msg("num=" SIZE_FORMAT " str=\"%s\"", num, str));
347 case 5: fatal("expected null");
348 case 6: fatal(err_msg("num=" SIZE_FORMAT " str=\"%s\"", num, str));
349 case 7: fatal(err_msg("%s%s# %s%s# %s%s# %s%s# %s%s# "
350 "%s%s# %s%s# %s%s# %s%s# %s%s# "
351 "%s%s# %s%s# %s%s# %s%s# %s",
352 msg, eol, msg, eol, msg, eol, msg, eol, msg, eol,
353 msg, eol, msg, eol, msg, eol, msg, eol, msg, eol,
354 msg, eol, msg, eol, msg, eol, msg, eol, msg));
355 case 8: vm_exit_out_of_memory(num, "ChunkPool::allocate");
356 case 9: ShouldNotCallThis();
357 case 10: ShouldNotReachHere();
358 case 11: Unimplemented();
359 // This is last because it does not generate an hs_err* file on Windows.
360 case 12: os::signal_raise(SIGSEGV);
362 default: ShouldNotReachHere();
363 }
364 }
365 #endif // #ifndef PRODUCT
367 // ------ helper functions for debugging go here ------------
369 #ifndef PRODUCT
370 // All debug entries should be wrapped with a stack allocated
371 // Command object. It makes sure a resource mark is set and
372 // flushes the logfile to prevent file sharing problems.
374 class Command : public StackObj {
375 private:
376 ResourceMark rm;
377 ResetNoHandleMark rnhm;
378 HandleMark hm;
379 bool debug_save;
380 public:
381 static int level;
382 Command(const char* str) {
383 debug_save = Debugging;
384 Debugging = true;
385 if (level++ > 0) return;
386 tty->cr();
387 tty->print_cr("\"Executing %s\"", str);
388 }
390 ~Command() { tty->flush(); Debugging = debug_save; level--; }
391 };
393 int Command::level = 0;
395 extern "C" void blob(CodeBlob* cb) {
396 Command c("blob");
397 cb->print();
398 }
401 extern "C" void dump_vtable(address p) {
402 Command c("dump_vtable");
403 klassOop k = (klassOop)p;
404 instanceKlass::cast(k)->vtable()->print();
405 }
408 extern "C" void nm(intptr_t p) {
409 // Actually we look through all CodeBlobs (the nm name has been kept for backwards compatability)
410 Command c("nm");
411 CodeBlob* cb = CodeCache::find_blob((address)p);
412 if (cb == NULL) {
413 tty->print_cr("NULL");
414 } else {
415 cb->print();
416 }
417 }
420 extern "C" void disnm(intptr_t p) {
421 Command c("disnm");
422 CodeBlob* cb = CodeCache::find_blob((address) p);
423 nmethod* nm = cb->as_nmethod_or_null();
424 if (nm) {
425 nm->print();
426 Disassembler::decode(nm);
427 } else {
428 cb->print();
429 Disassembler::decode(cb);
430 }
431 }
434 extern "C" void printnm(intptr_t p) {
435 char buffer[256];
436 sprintf(buffer, "printnm: " INTPTR_FORMAT, p);
437 Command c(buffer);
438 CodeBlob* cb = CodeCache::find_blob((address) p);
439 if (cb->is_nmethod()) {
440 nmethod* nm = (nmethod*)cb;
441 nm->print_nmethod(true);
442 }
443 }
446 extern "C" void universe() {
447 Command c("universe");
448 Universe::print();
449 }
452 extern "C" void verify() {
453 // try to run a verify on the entire system
454 // note: this may not be safe if we're not at a safepoint; for debugging,
455 // this manipulates the safepoint settings to avoid assertion failures
456 Command c("universe verify");
457 bool safe = SafepointSynchronize::is_at_safepoint();
458 if (!safe) {
459 tty->print_cr("warning: not at safepoint -- verify may fail");
460 SafepointSynchronize::set_is_at_safepoint();
461 }
462 // Ensure Eden top is correct before verification
463 Universe::heap()->prepare_for_verify();
464 Universe::verify(true);
465 if (!safe) SafepointSynchronize::set_is_not_at_safepoint();
466 }
469 extern "C" void pp(void* p) {
470 Command c("pp");
471 FlagSetting fl(PrintVMMessages, true);
472 if (Universe::heap()->is_in(p)) {
473 oop obj = oop(p);
474 obj->print();
475 } else {
476 tty->print("%#p", p);
477 }
478 }
481 // pv: print vm-printable object
482 extern "C" void pa(intptr_t p) { ((AllocatedObj*) p)->print(); }
483 extern "C" void findpc(intptr_t x);
485 extern "C" void ps() { // print stack
486 Command c("ps");
489 // Prints the stack of the current Java thread
490 JavaThread* p = JavaThread::active();
491 tty->print(" for thread: ");
492 p->print();
493 tty->cr();
495 if (p->has_last_Java_frame()) {
496 // If the last_Java_fp is set we are in C land and
497 // can call the standard stack_trace function.
498 p->trace_stack();
499 } else {
500 frame f = os::current_frame();
501 RegisterMap reg_map(p);
502 f = f.sender(®_map);
503 tty->print("(guessing starting frame id=%#p based on current fp)\n", f.id());
504 p->trace_stack_from(vframe::new_vframe(&f, ®_map, p));
505 pd_ps(f);
506 }
508 }
511 extern "C" void psf() { // print stack frames
512 {
513 Command c("psf");
514 JavaThread* p = JavaThread::active();
515 tty->print(" for thread: ");
516 p->print();
517 tty->cr();
518 if (p->has_last_Java_frame()) {
519 p->trace_frames();
520 }
521 }
522 }
525 extern "C" void threads() {
526 Command c("threads");
527 Threads::print(false, true);
528 }
531 extern "C" void psd() {
532 Command c("psd");
533 SystemDictionary::print();
534 }
537 extern "C" void safepoints() {
538 Command c("safepoints");
539 SafepointSynchronize::print_state();
540 }
543 extern "C" void pss() { // print all stacks
544 Command c("pss");
545 Threads::print(true, true);
546 }
549 extern "C" void debug() { // to set things up for compiler debugging
550 Command c("debug");
551 WizardMode = true;
552 PrintVMMessages = PrintCompilation = true;
553 PrintInlining = PrintAssembly = true;
554 tty->flush();
555 }
558 extern "C" void ndebug() { // undo debug()
559 Command c("ndebug");
560 PrintCompilation = false;
561 PrintInlining = PrintAssembly = false;
562 tty->flush();
563 }
566 extern "C" void flush() {
567 Command c("flush");
568 tty->flush();
569 }
572 extern "C" void events() {
573 Command c("events");
574 Events::print_last(tty, 50);
575 }
578 extern "C" void nevents(int n) {
579 Command c("events");
580 Events::print_last(tty, n);
581 }
584 // Given a heap address that was valid before the most recent GC, if
585 // the oop that used to contain it is still live, prints the new
586 // location of the oop and the address. Useful for tracking down
587 // certain kinds of naked oop and oop map bugs.
588 extern "C" void pnl(intptr_t old_heap_addr) {
589 // Print New Location of old heap address
590 Command c("pnl");
591 #ifndef VALIDATE_MARK_SWEEP
592 tty->print_cr("Requires build with VALIDATE_MARK_SWEEP defined (debug build) and RecordMarkSweepCompaction enabled");
593 #else
594 MarkSweep::print_new_location_of_heap_address((HeapWord*) old_heap_addr);
595 #endif
596 }
599 extern "C" methodOop findm(intptr_t pc) {
600 Command c("findm");
601 nmethod* nm = CodeCache::find_nmethod((address)pc);
602 return (nm == NULL) ? (methodOop)NULL : nm->method();
603 }
606 extern "C" nmethod* findnm(intptr_t addr) {
607 Command c("findnm");
608 return CodeCache::find_nmethod((address)addr);
609 }
611 static address same_page(address x, address y) {
612 intptr_t page_bits = -os::vm_page_size();
613 if ((intptr_t(x) & page_bits) == (intptr_t(y) & page_bits)) {
614 return x;
615 } else if (x > y) {
616 return (address)(intptr_t(y) | ~page_bits) + 1;
617 } else {
618 return (address)(intptr_t(y) & page_bits);
619 }
620 }
622 class LookForRefInGenClosure : public OopsInGenClosure {
623 public:
624 oop target;
625 void do_oop(oop* o) {
626 if (o != NULL && *o == target) {
627 tty->print_cr(INTPTR_FORMAT, o);
628 }
629 }
630 void do_oop(narrowOop* o) { ShouldNotReachHere(); }
631 };
634 class LookForRefInObjectClosure : public ObjectClosure {
635 private:
636 LookForRefInGenClosure look_in_object;
637 public:
638 LookForRefInObjectClosure(oop target) { look_in_object.target = target; }
639 void do_object(oop obj) {
640 obj->oop_iterate(&look_in_object);
641 }
642 };
645 static void findref(intptr_t x) {
646 CollectedHeap *ch = Universe::heap();
647 LookForRefInGenClosure lookFor;
648 lookFor.target = (oop) x;
649 LookForRefInObjectClosure look_in_object((oop) x);
651 tty->print_cr("Searching heap:");
652 ch->object_iterate(&look_in_object);
654 tty->print_cr("Searching strong roots:");
655 Universe::oops_do(&lookFor, false);
656 JNIHandles::oops_do(&lookFor); // Global (strong) JNI handles
657 Threads::oops_do(&lookFor, NULL);
658 ObjectSynchronizer::oops_do(&lookFor);
659 //FlatProfiler::oops_do(&lookFor);
660 SystemDictionary::oops_do(&lookFor);
662 tty->print_cr("Searching code cache:");
663 CodeCache::oops_do(&lookFor);
665 tty->print_cr("Done.");
666 }
668 class FindClassObjectClosure: public ObjectClosure {
669 private:
670 const char* _target;
671 public:
672 FindClassObjectClosure(const char name[]) { _target = name; }
674 virtual void do_object(oop obj) {
675 if (obj->is_klass()) {
676 Klass* k = klassOop(obj)->klass_part();
677 if (k->name() != NULL) {
678 ResourceMark rm;
679 const char* ext = k->external_name();
680 if ( strcmp(_target, ext) == 0 ) {
681 tty->print_cr("Found " INTPTR_FORMAT, obj);
682 obj->print();
683 }
684 }
685 }
686 }
687 };
689 //
690 extern "C" void findclass(const char name[]) {
691 Command c("findclass");
692 if (name != NULL) {
693 tty->print_cr("Finding class %s -> ", name);
694 FindClassObjectClosure srch(name);
695 Universe::heap()->permanent_object_iterate(&srch);
696 }
697 }
699 // Another interface that isn't ambiguous in dbx.
700 // Can we someday rename the other find to hsfind?
701 extern "C" void hsfind(intptr_t x) {
702 Command c("hsfind");
703 os::print_location(tty, x, false);
704 }
707 extern "C" void hsfindref(intptr_t x) {
708 Command c("hsfindref");
709 findref(x);
710 }
712 extern "C" void find(intptr_t x) {
713 Command c("find");
714 os::print_location(tty, x, false);
715 }
718 extern "C" void findpc(intptr_t x) {
719 Command c("findpc");
720 os::print_location(tty, x, true);
721 }
724 // int versions of all methods to avoid having to type type casts in the debugger
726 void pp(intptr_t p) { pp((void*)p); }
727 void pp(oop p) { pp((void*)p); }
729 void help() {
730 Command c("help");
731 tty->print_cr("basic");
732 tty->print_cr(" pp(void* p) - try to make sense of p");
733 tty->print_cr(" pv(intptr_t p)- ((PrintableResourceObj*) p)->print()");
734 tty->print_cr(" ps() - print current thread stack");
735 tty->print_cr(" pss() - print all thread stacks");
736 tty->print_cr(" pm(int pc) - print methodOop given compiled PC");
737 tty->print_cr(" findm(intptr_t pc) - finds methodOop");
738 tty->print_cr(" find(intptr_t x) - finds & prints nmethod/stub/bytecode/oop based on pointer into it");
740 tty->print_cr("misc.");
741 tty->print_cr(" flush() - flushes the log file");
742 tty->print_cr(" events() - dump last 50 events");
745 tty->print_cr("compiler debugging");
746 tty->print_cr(" debug() - to set things up for compiler debugging");
747 tty->print_cr(" ndebug() - undo debug");
748 }
750 #if 0
752 // BobV's command parser for debugging on windows when nothing else works.
754 enum CommandID {
755 CMDID_HELP,
756 CMDID_QUIT,
757 CMDID_HSFIND,
758 CMDID_PSS,
759 CMDID_PS,
760 CMDID_PSF,
761 CMDID_FINDM,
762 CMDID_FINDNM,
763 CMDID_PP,
764 CMDID_BPT,
765 CMDID_EXIT,
766 CMDID_VERIFY,
767 CMDID_THREADS,
768 CMDID_ILLEGAL = 99
769 };
771 struct CommandParser {
772 char *name;
773 CommandID code;
774 char *description;
775 };
777 struct CommandParser CommandList[] = {
778 (char *)"help", CMDID_HELP, " Dump this list",
779 (char *)"quit", CMDID_QUIT, " Return from this routine",
780 (char *)"hsfind", CMDID_HSFIND, "Perform an hsfind on an address",
781 (char *)"ps", CMDID_PS, " Print Current Thread Stack Trace",
782 (char *)"pss", CMDID_PSS, " Print All Thread Stack Trace",
783 (char *)"psf", CMDID_PSF, " Print All Stack Frames",
784 (char *)"findm", CMDID_FINDM, " Find a methodOop from a PC",
785 (char *)"findnm", CMDID_FINDNM, "Find an nmethod from a PC",
786 (char *)"pp", CMDID_PP, " Find out something about a pointer",
787 (char *)"break", CMDID_BPT, " Execute a breakpoint",
788 (char *)"exitvm", CMDID_EXIT, "Exit the VM",
789 (char *)"verify", CMDID_VERIFY, "Perform a Heap Verify",
790 (char *)"thread", CMDID_THREADS, "Dump Info on all Threads",
791 (char *)0, CMDID_ILLEGAL
792 };
795 // get_debug_command()
796 //
797 // Read a command from standard input.
798 // This is useful when you have a debugger
799 // which doesn't support calling into functions.
800 //
801 void get_debug_command()
802 {
803 ssize_t count;
804 int i,j;
805 bool gotcommand;
806 intptr_t addr;
807 char buffer[256];
808 nmethod *nm;
809 methodOop m;
811 tty->print_cr("You have entered the diagnostic command interpreter");
812 tty->print("The supported commands are:\n");
813 for ( i=0; ; i++ ) {
814 if ( CommandList[i].code == CMDID_ILLEGAL )
815 break;
816 tty->print_cr(" %s \n", CommandList[i].name );
817 }
819 while ( 1 ) {
820 gotcommand = false;
821 tty->print("Please enter a command: ");
822 count = scanf("%s", buffer) ;
823 if ( count >=0 ) {
824 for ( i=0; ; i++ ) {
825 if ( CommandList[i].code == CMDID_ILLEGAL ) {
826 if (!gotcommand) tty->print("Invalid command, please try again\n");
827 break;
828 }
829 if ( strcmp(buffer, CommandList[i].name) == 0 ) {
830 gotcommand = true;
831 switch ( CommandList[i].code ) {
832 case CMDID_PS:
833 ps();
834 break;
835 case CMDID_PSS:
836 pss();
837 break;
838 case CMDID_PSF:
839 psf();
840 break;
841 case CMDID_FINDM:
842 tty->print("Please enter the hex addr to pass to findm: ");
843 scanf("%I64X", &addr);
844 m = (methodOop)findm(addr);
845 tty->print("findm(0x%I64X) returned 0x%I64X\n", addr, m);
846 break;
847 case CMDID_FINDNM:
848 tty->print("Please enter the hex addr to pass to findnm: ");
849 scanf("%I64X", &addr);
850 nm = (nmethod*)findnm(addr);
851 tty->print("findnm(0x%I64X) returned 0x%I64X\n", addr, nm);
852 break;
853 case CMDID_PP:
854 tty->print("Please enter the hex addr to pass to pp: ");
855 scanf("%I64X", &addr);
856 pp((void*)addr);
857 break;
858 case CMDID_EXIT:
859 exit(0);
860 case CMDID_HELP:
861 tty->print("Here are the supported commands: ");
862 for ( j=0; ; j++ ) {
863 if ( CommandList[j].code == CMDID_ILLEGAL )
864 break;
865 tty->print_cr(" %s -- %s\n", CommandList[j].name,
866 CommandList[j].description );
867 }
868 break;
869 case CMDID_QUIT:
870 return;
871 break;
872 case CMDID_BPT:
873 BREAKPOINT;
874 break;
875 case CMDID_VERIFY:
876 verify();;
877 break;
878 case CMDID_THREADS:
879 threads();;
880 break;
881 case CMDID_HSFIND:
882 tty->print("Please enter the hex addr to pass to hsfind: ");
883 scanf("%I64X", &addr);
884 tty->print("Calling hsfind(0x%I64X)\n", addr);
885 hsfind(addr);
886 break;
887 default:
888 case CMDID_ILLEGAL:
889 break;
890 }
891 }
892 }
893 }
894 }
895 }
896 #endif
898 #endif // PRODUCT