Sat, 11 Dec 2010 13:20:56 -0500
7003748: Decode C stack frames when symbols are presented (PhoneHome project)
Summary: Implemented in-process C native stack frame decoding when symbols are available.
Reviewed-by: coleenp, 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 || error_is_suppressed(file, line)) 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_java_out_of_memory(const char* message) {
267 static jint out_of_memory_reported = 0;
269 // A number of threads may attempt to report OutOfMemoryError at around the
270 // same time. To avoid dumping the heap or executing the data collection
271 // commands multiple times we just do it once when the first threads reports
272 // the error.
273 if (Atomic::cmpxchg(1, &out_of_memory_reported, 0) == 0) {
274 // create heap dump before OnOutOfMemoryError commands are executed
275 if (HeapDumpOnOutOfMemoryError) {
276 tty->print_cr("java.lang.OutOfMemoryError: %s", message);
277 HeapDumper::dump_heap_from_oome();
278 }
280 if (OnOutOfMemoryError && OnOutOfMemoryError[0]) {
281 VMError err(message);
282 err.report_java_out_of_memory();
283 }
284 }
285 }
288 extern "C" void ps();
290 static bool error_reported = false;
292 // call this when the VM is dying--it might loosen some asserts
293 void set_error_reported() {
294 error_reported = true;
295 }
297 bool is_error_reported() {
298 return error_reported;
299 }
301 #ifndef PRODUCT
302 #include <signal.h>
304 void test_error_handler(size_t test_num)
305 {
306 if (test_num == 0) return;
308 // If asserts are disabled, use the corresponding guarantee instead.
309 size_t n = test_num;
310 NOT_DEBUG(if (n <= 2) n += 2);
312 const char* const str = "hello";
313 const size_t num = (size_t)os::vm_page_size();
315 const char* const eol = os::line_separator();
316 const char* const msg = "this message should be truncated during formatting";
318 // Keep this in sync with test/runtime/6888954/vmerrors.sh.
319 switch (n) {
320 case 1: assert(str == NULL, "expected null");
321 case 2: assert(num == 1023 && *str == 'X',
322 err_msg("num=" SIZE_FORMAT " str=\"%s\"", num, str));
323 case 3: guarantee(str == NULL, "expected null");
324 case 4: guarantee(num == 1023 && *str == 'X',
325 err_msg("num=" SIZE_FORMAT " str=\"%s\"", num, str));
326 case 5: fatal("expected null");
327 case 6: fatal(err_msg("num=" SIZE_FORMAT " str=\"%s\"", num, str));
328 case 7: fatal(err_msg("%s%s# %s%s# %s%s# %s%s# %s%s# "
329 "%s%s# %s%s# %s%s# %s%s# %s%s# "
330 "%s%s# %s%s# %s%s# %s%s# %s",
331 msg, eol, msg, eol, msg, eol, msg, eol, msg, eol,
332 msg, eol, msg, eol, msg, eol, msg, eol, msg, eol,
333 msg, eol, msg, eol, msg, eol, msg, eol, msg));
334 case 8: vm_exit_out_of_memory(num, "ChunkPool::allocate");
335 case 9: ShouldNotCallThis();
336 case 10: ShouldNotReachHere();
337 case 11: Unimplemented();
338 // This is last because it does not generate an hs_err* file on Windows.
339 case 12: os::signal_raise(SIGSEGV);
341 default: ShouldNotReachHere();
342 }
343 }
344 #endif // #ifndef PRODUCT
346 // ------ helper functions for debugging go here ------------
348 #ifndef PRODUCT
349 // All debug entries should be wrapped with a stack allocated
350 // Command object. It makes sure a resource mark is set and
351 // flushes the logfile to prevent file sharing problems.
353 class Command : public StackObj {
354 private:
355 ResourceMark rm;
356 ResetNoHandleMark rnhm;
357 HandleMark hm;
358 bool debug_save;
359 public:
360 static int level;
361 Command(const char* str) {
362 debug_save = Debugging;
363 Debugging = true;
364 if (level++ > 0) return;
365 tty->cr();
366 tty->print_cr("\"Executing %s\"", str);
367 }
369 ~Command() { tty->flush(); Debugging = debug_save; level--; }
370 };
372 int Command::level = 0;
374 extern "C" void blob(CodeBlob* cb) {
375 Command c("blob");
376 cb->print();
377 }
380 extern "C" void dump_vtable(address p) {
381 Command c("dump_vtable");
382 klassOop k = (klassOop)p;
383 instanceKlass::cast(k)->vtable()->print();
384 }
387 extern "C" void nm(intptr_t p) {
388 // Actually we look through all CodeBlobs (the nm name has been kept for backwards compatability)
389 Command c("nm");
390 CodeBlob* cb = CodeCache::find_blob((address)p);
391 if (cb == NULL) {
392 tty->print_cr("NULL");
393 } else {
394 cb->print();
395 }
396 }
399 extern "C" void disnm(intptr_t p) {
400 Command c("disnm");
401 CodeBlob* cb = CodeCache::find_blob((address) p);
402 cb->print();
403 Disassembler::decode(cb);
404 }
407 extern "C" void printnm(intptr_t p) {
408 char buffer[256];
409 sprintf(buffer, "printnm: " INTPTR_FORMAT, p);
410 Command c(buffer);
411 CodeBlob* cb = CodeCache::find_blob((address) p);
412 if (cb->is_nmethod()) {
413 nmethod* nm = (nmethod*)cb;
414 nm->print_nmethod(true);
415 }
416 }
419 extern "C" void universe() {
420 Command c("universe");
421 Universe::print();
422 }
425 extern "C" void verify() {
426 // try to run a verify on the entire system
427 // note: this may not be safe if we're not at a safepoint; for debugging,
428 // this manipulates the safepoint settings to avoid assertion failures
429 Command c("universe verify");
430 bool safe = SafepointSynchronize::is_at_safepoint();
431 if (!safe) {
432 tty->print_cr("warning: not at safepoint -- verify may fail");
433 SafepointSynchronize::set_is_at_safepoint();
434 }
435 // Ensure Eden top is correct before verification
436 Universe::heap()->prepare_for_verify();
437 Universe::verify(true);
438 if (!safe) SafepointSynchronize::set_is_not_at_safepoint();
439 }
442 extern "C" void pp(void* p) {
443 Command c("pp");
444 FlagSetting fl(PrintVMMessages, true);
445 if (Universe::heap()->is_in(p)) {
446 oop obj = oop(p);
447 obj->print();
448 } else {
449 tty->print("%#p", p);
450 }
451 }
454 // pv: print vm-printable object
455 extern "C" void pa(intptr_t p) { ((AllocatedObj*) p)->print(); }
456 extern "C" void findpc(intptr_t x);
458 extern "C" void ps() { // print stack
459 Command c("ps");
462 // Prints the stack of the current Java thread
463 JavaThread* p = JavaThread::active();
464 tty->print(" for thread: ");
465 p->print();
466 tty->cr();
468 if (p->has_last_Java_frame()) {
469 // If the last_Java_fp is set we are in C land and
470 // can call the standard stack_trace function.
471 p->trace_stack();
472 } else {
473 frame f = os::current_frame();
474 RegisterMap reg_map(p);
475 f = f.sender(®_map);
476 tty->print("(guessing starting frame id=%#p based on current fp)\n", f.id());
477 p->trace_stack_from(vframe::new_vframe(&f, ®_map, p));
478 pd_ps(f);
479 }
481 }
484 extern "C" void psf() { // print stack frames
485 {
486 Command c("psf");
487 JavaThread* p = JavaThread::active();
488 tty->print(" for thread: ");
489 p->print();
490 tty->cr();
491 if (p->has_last_Java_frame()) {
492 p->trace_frames();
493 }
494 }
495 }
498 extern "C" void threads() {
499 Command c("threads");
500 Threads::print(false, true);
501 }
504 extern "C" void psd() {
505 Command c("psd");
506 SystemDictionary::print();
507 }
510 extern "C" void safepoints() {
511 Command c("safepoints");
512 SafepointSynchronize::print_state();
513 }
516 extern "C" void pss() { // print all stacks
517 Command c("pss");
518 Threads::print(true, true);
519 }
522 extern "C" void debug() { // to set things up for compiler debugging
523 Command c("debug");
524 WizardMode = true;
525 PrintVMMessages = PrintCompilation = true;
526 PrintInlining = PrintAssembly = true;
527 tty->flush();
528 }
531 extern "C" void ndebug() { // undo debug()
532 Command c("ndebug");
533 PrintCompilation = false;
534 PrintInlining = PrintAssembly = false;
535 tty->flush();
536 }
539 extern "C" void flush() {
540 Command c("flush");
541 tty->flush();
542 }
545 extern "C" void events() {
546 Command c("events");
547 Events::print_last(tty, 50);
548 }
551 extern "C" void nevents(int n) {
552 Command c("events");
553 Events::print_last(tty, n);
554 }
557 // Given a heap address that was valid before the most recent GC, if
558 // the oop that used to contain it is still live, prints the new
559 // location of the oop and the address. Useful for tracking down
560 // certain kinds of naked oop and oop map bugs.
561 extern "C" void pnl(intptr_t old_heap_addr) {
562 // Print New Location of old heap address
563 Command c("pnl");
564 #ifndef VALIDATE_MARK_SWEEP
565 tty->print_cr("Requires build with VALIDATE_MARK_SWEEP defined (debug build) and RecordMarkSweepCompaction enabled");
566 #else
567 MarkSweep::print_new_location_of_heap_address((HeapWord*) old_heap_addr);
568 #endif
569 }
572 extern "C" methodOop findm(intptr_t pc) {
573 Command c("findm");
574 nmethod* nm = CodeCache::find_nmethod((address)pc);
575 return (nm == NULL) ? (methodOop)NULL : nm->method();
576 }
579 extern "C" nmethod* findnm(intptr_t addr) {
580 Command c("findnm");
581 return CodeCache::find_nmethod((address)addr);
582 }
584 static address same_page(address x, address y) {
585 intptr_t page_bits = -os::vm_page_size();
586 if ((intptr_t(x) & page_bits) == (intptr_t(y) & page_bits)) {
587 return x;
588 } else if (x > y) {
589 return (address)(intptr_t(y) | ~page_bits) + 1;
590 } else {
591 return (address)(intptr_t(y) & page_bits);
592 }
593 }
595 class LookForRefInGenClosure : public OopsInGenClosure {
596 public:
597 oop target;
598 void do_oop(oop* o) {
599 if (o != NULL && *o == target) {
600 tty->print_cr(INTPTR_FORMAT, o);
601 }
602 }
603 void do_oop(narrowOop* o) { ShouldNotReachHere(); }
604 };
607 class LookForRefInObjectClosure : public ObjectClosure {
608 private:
609 LookForRefInGenClosure look_in_object;
610 public:
611 LookForRefInObjectClosure(oop target) { look_in_object.target = target; }
612 void do_object(oop obj) {
613 obj->oop_iterate(&look_in_object);
614 }
615 };
618 static void findref(intptr_t x) {
619 CollectedHeap *ch = Universe::heap();
620 LookForRefInGenClosure lookFor;
621 lookFor.target = (oop) x;
622 LookForRefInObjectClosure look_in_object((oop) x);
624 tty->print_cr("Searching heap:");
625 ch->object_iterate(&look_in_object);
627 tty->print_cr("Searching strong roots:");
628 Universe::oops_do(&lookFor, false);
629 JNIHandles::oops_do(&lookFor); // Global (strong) JNI handles
630 Threads::oops_do(&lookFor, NULL);
631 ObjectSynchronizer::oops_do(&lookFor);
632 //FlatProfiler::oops_do(&lookFor);
633 SystemDictionary::oops_do(&lookFor);
635 tty->print_cr("Searching code cache:");
636 CodeCache::oops_do(&lookFor);
638 tty->print_cr("Done.");
639 }
641 class FindClassObjectClosure: public ObjectClosure {
642 private:
643 const char* _target;
644 public:
645 FindClassObjectClosure(const char name[]) { _target = name; }
647 virtual void do_object(oop obj) {
648 if (obj->is_klass()) {
649 Klass* k = klassOop(obj)->klass_part();
650 if (k->name() != NULL) {
651 ResourceMark rm;
652 const char* ext = k->external_name();
653 if ( strcmp(_target, ext) == 0 ) {
654 tty->print_cr("Found " INTPTR_FORMAT, obj);
655 obj->print();
656 }
657 }
658 }
659 }
660 };
662 //
663 extern "C" void findclass(const char name[]) {
664 Command c("findclass");
665 if (name != NULL) {
666 tty->print_cr("Finding class %s -> ", name);
667 FindClassObjectClosure srch(name);
668 Universe::heap()->permanent_object_iterate(&srch);
669 }
670 }
672 // Another interface that isn't ambiguous in dbx.
673 // Can we someday rename the other find to hsfind?
674 extern "C" void hsfind(intptr_t x) {
675 Command c("hsfind");
676 os::print_location(tty, x, false);
677 }
680 extern "C" void hsfindref(intptr_t x) {
681 Command c("hsfindref");
682 findref(x);
683 }
685 extern "C" void find(intptr_t x) {
686 Command c("find");
687 os::print_location(tty, x, false);
688 }
691 extern "C" void findpc(intptr_t x) {
692 Command c("findpc");
693 os::print_location(tty, x, true);
694 }
697 // int versions of all methods to avoid having to type type casts in the debugger
699 void pp(intptr_t p) { pp((void*)p); }
700 void pp(oop p) { pp((void*)p); }
702 void help() {
703 Command c("help");
704 tty->print_cr("basic");
705 tty->print_cr(" pp(void* p) - try to make sense of p");
706 tty->print_cr(" pv(intptr_t p)- ((PrintableResourceObj*) p)->print()");
707 tty->print_cr(" ps() - print current thread stack");
708 tty->print_cr(" pss() - print all thread stacks");
709 tty->print_cr(" pm(int pc) - print methodOop given compiled PC");
710 tty->print_cr(" findm(intptr_t pc) - finds methodOop");
711 tty->print_cr(" find(intptr_t x) - finds & prints nmethod/stub/bytecode/oop based on pointer into it");
713 tty->print_cr("misc.");
714 tty->print_cr(" flush() - flushes the log file");
715 tty->print_cr(" events() - dump last 50 events");
718 tty->print_cr("compiler debugging");
719 tty->print_cr(" debug() - to set things up for compiler debugging");
720 tty->print_cr(" ndebug() - undo debug");
721 }
723 #if 0
725 // BobV's command parser for debugging on windows when nothing else works.
727 enum CommandID {
728 CMDID_HELP,
729 CMDID_QUIT,
730 CMDID_HSFIND,
731 CMDID_PSS,
732 CMDID_PS,
733 CMDID_PSF,
734 CMDID_FINDM,
735 CMDID_FINDNM,
736 CMDID_PP,
737 CMDID_BPT,
738 CMDID_EXIT,
739 CMDID_VERIFY,
740 CMDID_THREADS,
741 CMDID_ILLEGAL = 99
742 };
744 struct CommandParser {
745 char *name;
746 CommandID code;
747 char *description;
748 };
750 struct CommandParser CommandList[] = {
751 (char *)"help", CMDID_HELP, " Dump this list",
752 (char *)"quit", CMDID_QUIT, " Return from this routine",
753 (char *)"hsfind", CMDID_HSFIND, "Perform an hsfind on an address",
754 (char *)"ps", CMDID_PS, " Print Current Thread Stack Trace",
755 (char *)"pss", CMDID_PSS, " Print All Thread Stack Trace",
756 (char *)"psf", CMDID_PSF, " Print All Stack Frames",
757 (char *)"findm", CMDID_FINDM, " Find a methodOop from a PC",
758 (char *)"findnm", CMDID_FINDNM, "Find an nmethod from a PC",
759 (char *)"pp", CMDID_PP, " Find out something about a pointer",
760 (char *)"break", CMDID_BPT, " Execute a breakpoint",
761 (char *)"exitvm", CMDID_EXIT, "Exit the VM",
762 (char *)"verify", CMDID_VERIFY, "Perform a Heap Verify",
763 (char *)"thread", CMDID_THREADS, "Dump Info on all Threads",
764 (char *)0, CMDID_ILLEGAL
765 };
768 // get_debug_command()
769 //
770 // Read a command from standard input.
771 // This is useful when you have a debugger
772 // which doesn't support calling into functions.
773 //
774 void get_debug_command()
775 {
776 ssize_t count;
777 int i,j;
778 bool gotcommand;
779 intptr_t addr;
780 char buffer[256];
781 nmethod *nm;
782 methodOop m;
784 tty->print_cr("You have entered the diagnostic command interpreter");
785 tty->print("The supported commands are:\n");
786 for ( i=0; ; i++ ) {
787 if ( CommandList[i].code == CMDID_ILLEGAL )
788 break;
789 tty->print_cr(" %s \n", CommandList[i].name );
790 }
792 while ( 1 ) {
793 gotcommand = false;
794 tty->print("Please enter a command: ");
795 count = scanf("%s", buffer) ;
796 if ( count >=0 ) {
797 for ( i=0; ; i++ ) {
798 if ( CommandList[i].code == CMDID_ILLEGAL ) {
799 if (!gotcommand) tty->print("Invalid command, please try again\n");
800 break;
801 }
802 if ( strcmp(buffer, CommandList[i].name) == 0 ) {
803 gotcommand = true;
804 switch ( CommandList[i].code ) {
805 case CMDID_PS:
806 ps();
807 break;
808 case CMDID_PSS:
809 pss();
810 break;
811 case CMDID_PSF:
812 psf();
813 break;
814 case CMDID_FINDM:
815 tty->print("Please enter the hex addr to pass to findm: ");
816 scanf("%I64X", &addr);
817 m = (methodOop)findm(addr);
818 tty->print("findm(0x%I64X) returned 0x%I64X\n", addr, m);
819 break;
820 case CMDID_FINDNM:
821 tty->print("Please enter the hex addr to pass to findnm: ");
822 scanf("%I64X", &addr);
823 nm = (nmethod*)findnm(addr);
824 tty->print("findnm(0x%I64X) returned 0x%I64X\n", addr, nm);
825 break;
826 case CMDID_PP:
827 tty->print("Please enter the hex addr to pass to pp: ");
828 scanf("%I64X", &addr);
829 pp((void*)addr);
830 break;
831 case CMDID_EXIT:
832 exit(0);
833 case CMDID_HELP:
834 tty->print("Here are the supported commands: ");
835 for ( j=0; ; j++ ) {
836 if ( CommandList[j].code == CMDID_ILLEGAL )
837 break;
838 tty->print_cr(" %s -- %s\n", CommandList[j].name,
839 CommandList[j].description );
840 }
841 break;
842 case CMDID_QUIT:
843 return;
844 break;
845 case CMDID_BPT:
846 BREAKPOINT;
847 break;
848 case CMDID_VERIFY:
849 verify();;
850 break;
851 case CMDID_THREADS:
852 threads();;
853 break;
854 case CMDID_HSFIND:
855 tty->print("Please enter the hex addr to pass to hsfind: ");
856 scanf("%I64X", &addr);
857 tty->print("Calling hsfind(0x%I64X)\n", addr);
858 hsfind(addr);
859 break;
860 default:
861 case CMDID_ILLEGAL:
862 break;
863 }
864 }
865 }
866 }
867 }
868 }
869 #endif
871 #endif // PRODUCT