debug.cpp revision 4558:746b070f5022
1130561Sobrien/* 2130561Sobrien * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. 3130561Sobrien * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4130561Sobrien * 5130561Sobrien * This code is free software; you can redistribute it and/or modify it 6130561Sobrien * under the terms of the GNU General Public License version 2 only, as 7130561Sobrien * published by the Free Software Foundation. 8130561Sobrien * 9130561Sobrien * This code is distributed in the hope that it will be useful, but WITHOUT 10130561Sobrien * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11130561Sobrien * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12130561Sobrien * version 2 for more details (a copy is included in the LICENSE file that 13130561Sobrien * accompanied this code). 14130561Sobrien * 15130561Sobrien * You should have received a copy of the GNU General Public License version 16130561Sobrien * 2 along with this work; if not, write to the Free Software Foundation, 17130561Sobrien * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18130561Sobrien * 19130561Sobrien * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20130561Sobrien * or visit www.oracle.com if you need additional information or have any 21130561Sobrien * questions. 22130561Sobrien * 23130561Sobrien */ 24130561Sobrien 25130561Sobrien#include "precompiled.hpp" 26130561Sobrien#include "classfile/systemDictionary.hpp" 27130561Sobrien#include "code/codeCache.hpp" 28130561Sobrien#include "code/icBuffer.hpp" 29130561Sobrien#include "code/nmethod.hpp" 30130561Sobrien#include "code/vtableStubs.hpp" 31130561Sobrien#include "compiler/compileBroker.hpp" 32130561Sobrien#include "compiler/disassembler.hpp" 33130561Sobrien#include "gc_implementation/shared/markSweep.hpp" 34130561Sobrien#include "gc_interface/collectedHeap.hpp" 35130561Sobrien#include "interpreter/bytecodeHistogram.hpp" 36130561Sobrien#include "interpreter/interpreter.hpp" 37130561Sobrien#include "memory/resourceArea.hpp" 38130561Sobrien#include "memory/universe.hpp" 39130561Sobrien#include "oops/oop.inline.hpp" 40130561Sobrien#include "prims/privilegedStack.hpp" 41130561Sobrien#include "runtime/arguments.hpp" 42130561Sobrien#include "runtime/frame.hpp" 43130561Sobrien#include "runtime/java.hpp" 44130561Sobrien#include "runtime/sharedRuntime.hpp" 45130561Sobrien#include "runtime/stubCodeGenerator.hpp" 46130561Sobrien#include "runtime/stubRoutines.hpp" 47130561Sobrien#include "runtime/thread.inline.hpp" 48130561Sobrien#include "runtime/vframe.hpp" 49130561Sobrien#include "services/heapDumper.hpp" 50130561Sobrien#include "utilities/defaultStream.hpp" 51130561Sobrien#include "utilities/events.hpp" 52130561Sobrien#include "utilities/top.hpp" 53130561Sobrien#include "utilities/vmError.hpp" 54130561Sobrien#ifdef TARGET_OS_FAMILY_linux 55130561Sobrien# include "os_linux.inline.hpp" 56130561Sobrien#endif 57130561Sobrien#ifdef TARGET_OS_FAMILY_solaris 58130561Sobrien# include "os_solaris.inline.hpp" 59130561Sobrien#endif 60130561Sobrien#ifdef TARGET_OS_FAMILY_windows 61130561Sobrien# include "os_windows.inline.hpp" 62130561Sobrien#endif 63130561Sobrien#ifdef TARGET_OS_FAMILY_bsd 64130561Sobrien# include "os_bsd.inline.hpp" 65130561Sobrien#endif 66130561Sobrien 67130561Sobrien#ifndef ASSERT 68130561Sobrien# ifdef _DEBUG 69130561Sobrien // NOTE: don't turn the lines below into a comment -- if you're getting 70130561Sobrien // a compile error here, change the settings to define ASSERT 71130561Sobrien ASSERT should be defined when _DEBUG is defined. It is not intended to be used for debugging 72130561Sobrien functions that do not slow down the system too much and thus can be left in optimized code. 73130561Sobrien On the other hand, the code should not be included in a production version. 74130561Sobrien# endif // _DEBUG 75130561Sobrien#endif // ASSERT 76130561Sobrien 77130561Sobrien 78130561Sobrien#ifdef _DEBUG 79130561Sobrien# ifndef ASSERT 80130561Sobrien configuration error: ASSERT must be defined in debug version 81130561Sobrien# endif // ASSERT 82130561Sobrien#endif // _DEBUG 83130561Sobrien 84130561Sobrien 85130561Sobrien#ifdef PRODUCT 86130561Sobrien# if -defined _DEBUG || -defined ASSERT 87130561Sobrien configuration error: ASSERT et al. must not be defined in PRODUCT version 88130561Sobrien# endif 89130561Sobrien#endif // PRODUCT 90130561Sobrien 91130561SobrienFormatBufferResource::FormatBufferResource(const char * format, ...) 92130561Sobrien : FormatBufferBase((char*)resource_allocate_bytes(RES_BUFSZ)) { 93130561Sobrien va_list argp; 94130561Sobrien va_start(argp, format); 95130561Sobrien jio_vsnprintf(_buf, RES_BUFSZ, format, argp); 96130561Sobrien va_end(argp); 97130561Sobrien} 98130561Sobrien 99130561Sobrienvoid warning(const char* format, ...) { 100130561Sobrien if (PrintWarnings) { 101130561Sobrien FILE* const err = defaultStream::error_stream(); 102130561Sobrien jio_fprintf(err, "%s warning: ", VM_Version::vm_name()); 103130561Sobrien va_list ap; 104130561Sobrien va_start(ap, format); 105130561Sobrien vfprintf(err, format, ap); 106130561Sobrien va_end(ap); 107130561Sobrien fputc('\n', err); 108130561Sobrien } 109130561Sobrien if (BreakAtWarning) BREAKPOINT; 110130561Sobrien} 111130561Sobrien 112130561Sobrien#ifndef PRODUCT 113130561Sobrien 114130561Sobrien#define is_token_break(ch) (isspace(ch) || (ch) == ',') 115130561Sobrien 116130561Sobrienstatic const char* last_file_name = NULL; 117130561Sobrienstatic int last_line_no = -1; 118130561Sobrien 119130561Sobrien// assert/guarantee/... may happen very early during VM initialization. 120130561Sobrien// Don't rely on anything that is initialized by Threads::create_vm(). For 121130561Sobrien// example, don't use tty. 122130561Sobrienbool error_is_suppressed(const char* file_name, int line_no) { 123130561Sobrien // The following 1-element cache requires that passed-in 124130561Sobrien // file names are always only constant literals. 125130561Sobrien if (file_name == last_file_name && line_no == last_line_no) return true; 126130561Sobrien 127130561Sobrien int file_name_len = (int)strlen(file_name); 128130561Sobrien char separator = os::file_separator()[0]; 129130561Sobrien const char* base_name = strrchr(file_name, separator); 130130561Sobrien if (base_name == NULL) 131130561Sobrien base_name = file_name; 132130561Sobrien 133130561Sobrien // scan the SuppressErrorAt option 134130561Sobrien const char* cp = SuppressErrorAt; 135130561Sobrien for (;;) { 136130561Sobrien const char* sfile; 137130561Sobrien int sfile_len; 138130561Sobrien int sline; 139130561Sobrien bool noisy; 140130561Sobrien while ((*cp) != '\0' && is_token_break(*cp)) cp++; 141130561Sobrien if ((*cp) == '\0') break; 142130561Sobrien sfile = cp; 143130561Sobrien while ((*cp) != '\0' && !is_token_break(*cp) && (*cp) != ':') cp++; 144130561Sobrien sfile_len = cp - sfile; 145130561Sobrien if ((*cp) == ':') cp++; 146130561Sobrien sline = 0; 147130561Sobrien while ((*cp) != '\0' && isdigit(*cp)) { 148130561Sobrien sline *= 10; 149130561Sobrien sline += (*cp) - '0'; 150130561Sobrien cp++; 151130561Sobrien } 152130561Sobrien // "file:line!" means the assert suppression is not silent 153130561Sobrien noisy = ((*cp) == '!'); 154130561Sobrien while ((*cp) != '\0' && !is_token_break(*cp)) cp++; 155130561Sobrien // match the line 156130561Sobrien if (sline != 0) { 157130561Sobrien if (sline != line_no) continue; 158130561Sobrien } 159130561Sobrien // match the file 160130561Sobrien if (sfile_len > 0) { 161130561Sobrien const char* look = file_name; 162130561Sobrien const char* look_max = file_name + file_name_len - sfile_len; 163130561Sobrien const char* foundp; 164130561Sobrien bool match = false; 165130561Sobrien while (!match 166130561Sobrien && (foundp = strchr(look, sfile[0])) != NULL 167130561Sobrien && foundp <= look_max) { 168130561Sobrien match = true; 169130561Sobrien for (int i = 1; i < sfile_len; i++) { 170130561Sobrien if (sfile[i] != foundp[i]) { 171130561Sobrien match = false; 172130561Sobrien break; 173130561Sobrien } 174130561Sobrien } 175130561Sobrien look = foundp + 1; 176130561Sobrien } 177130561Sobrien if (!match) continue; 178130561Sobrien } 179130561Sobrien // got a match! 180130561Sobrien if (noisy) { 181130561Sobrien fdStream out(defaultStream::output_fd()); 182130561Sobrien out.print_raw("[error suppressed at "); 183130561Sobrien out.print_raw(base_name); 184130561Sobrien char buf[16]; 185130561Sobrien jio_snprintf(buf, sizeof(buf), ":%d]", line_no); 186130561Sobrien out.print_raw_cr(buf); 187130561Sobrien } else { 188130561Sobrien // update 1-element cache for fast silent matches 189130561Sobrien last_file_name = file_name; 190130561Sobrien last_line_no = line_no; 191130561Sobrien } 192130561Sobrien return true; 193130561Sobrien } 194130561Sobrien 195130561Sobrien if (!is_error_reported()) { 196130561Sobrien // print a friendly hint: 197130561Sobrien fdStream out(defaultStream::output_fd()); 198130561Sobrien out.print_raw_cr("# To suppress the following error report, specify this argument"); 199130561Sobrien out.print_raw ("# after -XX: or in .hotspotrc: SuppressErrorAt="); 200130561Sobrien out.print_raw (base_name); 201130561Sobrien char buf[16]; 202130561Sobrien jio_snprintf(buf, sizeof(buf), ":%d", line_no); 203130561Sobrien out.print_raw_cr(buf); 204130561Sobrien } 205130561Sobrien return false; 206130561Sobrien} 207130561Sobrien 208130561Sobrien#undef is_token_break 209130561Sobrien 210130561Sobrien#else 211130561Sobrien 212130561Sobrien// Place-holder for non-existent suppression check: 213130561Sobrien#define error_is_suppressed(file_name, line_no) (false) 214130561Sobrien 215130561Sobrien#endif // !PRODUCT 216130561Sobrien 217130561Sobrienvoid report_vm_error(const char* file, int line, const char* error_msg, 218130561Sobrien const char* detail_msg) 219130561Sobrien{ 220130561Sobrien if (Debugging || error_is_suppressed(file, line)) return; 221130561Sobrien Thread* const thread = ThreadLocalStorage::get_thread_slow(); 222130561Sobrien VMError err(thread, file, line, error_msg, detail_msg); 223130561Sobrien err.report_and_die(); 224130561Sobrien} 225130561Sobrien 226130561Sobrienvoid report_fatal(const char* file, int line, const char* message) 227130561Sobrien{ 228130561Sobrien report_vm_error(file, line, "fatal error", message); 229130561Sobrien} 230130561Sobrien 231130561Sobrienvoid report_vm_out_of_memory(const char* file, int line, size_t size, 232130561Sobrien VMErrorType vm_err_type, const char* message) { 233130561Sobrien if (Debugging) return; 234130561Sobrien 235130561Sobrien Thread* thread = ThreadLocalStorage::get_thread_slow(); 236130561Sobrien VMError(thread, file, line, size, vm_err_type, message).report_and_die(); 237130561Sobrien 238130561Sobrien // The UseOSErrorReporting option in report_and_die() may allow a return 239130561Sobrien // to here. If so then we'll have to figure out how to handle it. 240130561Sobrien guarantee(false, "report_and_die() should not return here"); 241130561Sobrien} 242130561Sobrien 243130561Sobrienvoid report_should_not_call(const char* file, int line) { 244130561Sobrien report_vm_error(file, line, "ShouldNotCall()"); 245130561Sobrien} 246130561Sobrien 247130561Sobrienvoid report_should_not_reach_here(const char* file, int line) { 248130561Sobrien report_vm_error(file, line, "ShouldNotReachHere()"); 249130561Sobrien} 250130561Sobrien 251130561Sobrienvoid report_unimplemented(const char* file, int line) { 252130561Sobrien report_vm_error(file, line, "Unimplemented()"); 253130561Sobrien} 254130561Sobrien 255130561Sobrienvoid report_untested(const char* file, int line, const char* message) { 256130561Sobrien#ifndef PRODUCT 257130561Sobrien warning("Untested: %s in %s: %d\n", message, file, line); 258130561Sobrien#endif // !PRODUCT 259130561Sobrien} 260130561Sobrien 261130561Sobrienvoid report_out_of_shared_space(SharedSpaceType shared_space) { 262130561Sobrien static const char* name[] = { 263130561Sobrien "native memory for metadata", 264130561Sobrien "shared read only space", 265130561Sobrien "shared read write space", 266130561Sobrien "shared miscellaneous data space" 267130561Sobrien }; 268130561Sobrien static const char* flag[] = { 269130561Sobrien "Metaspace", 270130561Sobrien "SharedReadOnlySize", 271130561Sobrien "SharedReadWriteSize", 272130561Sobrien "SharedMiscDataSize" 273130561Sobrien }; 274130561Sobrien 275130561Sobrien warning("\nThe %s is not large enough\n" 276130561Sobrien "to preload requested classes. Use -XX:%s=\n" 277130561Sobrien "to increase the initial size of %s.\n", 278130561Sobrien name[shared_space], flag[shared_space], name[shared_space]); 279130561Sobrien exit(2); 280130561Sobrien} 281130561Sobrien 282130561Sobrienvoid report_java_out_of_memory(const char* message) { 283130561Sobrien static jint out_of_memory_reported = 0; 284130561Sobrien 285130561Sobrien // A number of threads may attempt to report OutOfMemoryError at around the 286130561Sobrien // same time. To avoid dumping the heap or executing the data collection 287130561Sobrien // commands multiple times we just do it once when the first threads reports 288130561Sobrien // the error. 289130561Sobrien if (Atomic::cmpxchg(1, &out_of_memory_reported, 0) == 0) { 290130561Sobrien // create heap dump before OnOutOfMemoryError commands are executed 291130561Sobrien if (HeapDumpOnOutOfMemoryError) { 292130561Sobrien tty->print_cr("java.lang.OutOfMemoryError: %s", message); 293130561Sobrien HeapDumper::dump_heap_from_oome(); 294130561Sobrien } 295130561Sobrien 296130561Sobrien if (OnOutOfMemoryError && OnOutOfMemoryError[0]) { 297130561Sobrien VMError err(message); 298130561Sobrien err.report_java_out_of_memory(); 299130561Sobrien } 300130561Sobrien } 301130561Sobrien} 302130561Sobrien 303130561Sobrienstatic bool error_reported = false; 304130561Sobrien 305130561Sobrien// call this when the VM is dying--it might loosen some asserts 306130561Sobrienvoid set_error_reported() { 307130561Sobrien error_reported = true; 308130561Sobrien} 309130561Sobrien 310130561Sobrienbool is_error_reported() { 311130561Sobrien return error_reported; 312130561Sobrien} 313130561Sobrien 314130561Sobrien#ifndef PRODUCT 315130561Sobrien#include <signal.h> 316130561Sobrien 317130561Sobrienvoid test_error_handler(size_t test_num) 318130561Sobrien{ 319130561Sobrien if (test_num == 0) return; 320130561Sobrien 321130561Sobrien // If asserts are disabled, use the corresponding guarantee instead. 322130561Sobrien size_t n = test_num; 323130561Sobrien NOT_DEBUG(if (n <= 2) n += 2); 324130561Sobrien 325130561Sobrien const char* const str = "hello"; 326130561Sobrien const size_t num = (size_t)os::vm_page_size(); 327130561Sobrien 328130561Sobrien const char* const eol = os::line_separator(); 329130561Sobrien const char* const msg = "this message should be truncated during formatting"; 330130561Sobrien 331130561Sobrien // Keep this in sync with test/runtime/6888954/vmerrors.sh. 332130561Sobrien switch (n) { 333130561Sobrien case 1: assert(str == NULL, "expected null"); 334130561Sobrien case 2: assert(num == 1023 && *str == 'X', 335130561Sobrien err_msg("num=" SIZE_FORMAT " str=\"%s\"", num, str)); 336130561Sobrien case 3: guarantee(str == NULL, "expected null"); 337130561Sobrien case 4: guarantee(num == 1023 && *str == 'X', 338130561Sobrien err_msg("num=" SIZE_FORMAT " str=\"%s\"", num, str)); 339130561Sobrien case 5: fatal("expected null"); 340130561Sobrien case 6: fatal(err_msg("num=" SIZE_FORMAT " str=\"%s\"", num, str)); 341130561Sobrien case 7: fatal(err_msg("%s%s# %s%s# %s%s# %s%s# %s%s# " 342130561Sobrien "%s%s# %s%s# %s%s# %s%s# %s%s# " 343130561Sobrien "%s%s# %s%s# %s%s# %s%s# %s", 344130561Sobrien msg, eol, msg, eol, msg, eol, msg, eol, msg, eol, 345130561Sobrien msg, eol, msg, eol, msg, eol, msg, eol, msg, eol, 346130561Sobrien msg, eol, msg, eol, msg, eol, msg, eol, msg)); 347130561Sobrien case 8: vm_exit_out_of_memory(num, OOM_MALLOC_ERROR, "ChunkPool::allocate"); 348130561Sobrien case 9: ShouldNotCallThis(); 349130561Sobrien case 10: ShouldNotReachHere(); 350130561Sobrien case 11: Unimplemented(); 351130561Sobrien // This is last because it does not generate an hs_err* file on Windows. 352130561Sobrien case 12: os::signal_raise(SIGSEGV); 353130561Sobrien 354130561Sobrien default: ShouldNotReachHere(); 355130561Sobrien } 356130561Sobrien} 357130561Sobrien#endif // !PRODUCT 358130561Sobrien 359130561Sobrien// ------ helper functions for debugging go here ------------ 360130561Sobrien 361130561Sobrien// All debug entries should be wrapped with a stack allocated 362130561Sobrien// Command object. It makes sure a resource mark is set and 363130561Sobrien// flushes the logfile to prevent file sharing problems. 364130561Sobrien 365130561Sobrienclass Command : public StackObj { 366130561Sobrien private: 367130561Sobrien ResourceMark rm; 368130561Sobrien ResetNoHandleMark rnhm; 369130561Sobrien HandleMark hm; 370130561Sobrien bool debug_save; 371130561Sobrien public: 372130561Sobrien static int level; 373130561Sobrien Command(const char* str) { 374130561Sobrien debug_save = Debugging; 375130561Sobrien Debugging = true; 376130561Sobrien if (level++ > 0) return; 377130561Sobrien tty->cr(); 378130561Sobrien tty->print_cr("\"Executing %s\"", str); 379130561Sobrien } 380130561Sobrien 381130561Sobrien ~Command() { 382130561Sobrien tty->flush(); 383130561Sobrien Debugging = debug_save; 384130561Sobrien level--; 385130561Sobrien } 386130561Sobrien}; 387130561Sobrien 388130561Sobrienint Command::level = 0; 389130561Sobrien 390130561Sobrien#ifndef PRODUCT 391130561Sobrien 392130561Sobrienextern "C" void blob(CodeBlob* cb) { 393130561Sobrien Command c("blob"); 394130561Sobrien cb->print(); 395130561Sobrien} 396130561Sobrien 397130561Sobrien 398130561Sobrienextern "C" void dump_vtable(address p) { 399130561Sobrien Command c("dump_vtable"); 400130561Sobrien Klass* k = (Klass*)p; 401130561Sobrien InstanceKlass::cast(k)->vtable()->print(); 402130561Sobrien} 403130561Sobrien 404130561Sobrien 405130561Sobrienextern "C" void nm(intptr_t p) { 406130561Sobrien // Actually we look through all CodeBlobs (the nm name has been kept for backwards compatability) 407130561Sobrien Command c("nm"); 408130561Sobrien CodeBlob* cb = CodeCache::find_blob((address)p); 409130561Sobrien if (cb == NULL) { 410130561Sobrien tty->print_cr("NULL"); 411130561Sobrien } else { 412130561Sobrien cb->print(); 413130561Sobrien } 414130561Sobrien} 415130561Sobrien 416130561Sobrien 417130561Sobrienextern "C" void disnm(intptr_t p) { 418130561Sobrien Command c("disnm"); 419130561Sobrien CodeBlob* cb = CodeCache::find_blob((address) p); 420130561Sobrien nmethod* nm = cb->as_nmethod_or_null(); 421130561Sobrien if (nm) { 422130561Sobrien nm->print(); 423130561Sobrien Disassembler::decode(nm); 424130561Sobrien } else { 425130561Sobrien cb->print(); 426130561Sobrien Disassembler::decode(cb); 427130561Sobrien } 428130561Sobrien} 429130561Sobrien 430130561Sobrien 431130561Sobrienextern "C" void printnm(intptr_t p) { 432130561Sobrien char buffer[256]; 433130561Sobrien sprintf(buffer, "printnm: " INTPTR_FORMAT, p); 434130561Sobrien Command c(buffer); 435130561Sobrien CodeBlob* cb = CodeCache::find_blob((address) p); 436130561Sobrien if (cb->is_nmethod()) { 437130561Sobrien nmethod* nm = (nmethod*)cb; 438130561Sobrien nm->print_nmethod(true); 439130561Sobrien } 440130561Sobrien} 441130561Sobrien 442130561Sobrien 443130561Sobrienextern "C" void universe() { 444130561Sobrien Command c("universe"); 445130561Sobrien Universe::print(); 446130561Sobrien} 447130561Sobrien 448130561Sobrien 449130561Sobrienextern "C" void verify() { 450130561Sobrien // try to run a verify on the entire system 451130561Sobrien // note: this may not be safe if we're not at a safepoint; for debugging, 452130561Sobrien // this manipulates the safepoint settings to avoid assertion failures 453130561Sobrien Command c("universe verify"); 454130561Sobrien bool safe = SafepointSynchronize::is_at_safepoint(); 455130561Sobrien if (!safe) { 456130561Sobrien tty->print_cr("warning: not at safepoint -- verify may fail"); 457130561Sobrien SafepointSynchronize::set_is_at_safepoint(); 458130561Sobrien } 459130561Sobrien // Ensure Eden top is correct before verification 460130561Sobrien Universe::heap()->prepare_for_verify(); 461130561Sobrien Universe::verify(); 462130561Sobrien if (!safe) SafepointSynchronize::set_is_not_at_safepoint(); 463130561Sobrien} 464130561Sobrien 465130561Sobrien 466130561Sobrienextern "C" void pp(void* p) { 467130561Sobrien Command c("pp"); 468130561Sobrien FlagSetting fl(PrintVMMessages, true); 469130561Sobrien FlagSetting f2(DisplayVMOutput, true); 470130561Sobrien if (Universe::heap()->is_in(p)) { 471130561Sobrien oop obj = oop(p); 472130561Sobrien obj->print(); 473130561Sobrien } else { 474130561Sobrien tty->print(PTR_FORMAT, p); 475130561Sobrien } 476130561Sobrien} 477130561Sobrien 478130561Sobrien 479130561Sobrien// pv: print vm-printable object 480130561Sobrienextern "C" void pa(intptr_t p) { ((AllocatedObj*) p)->print(); } 481130561Sobrienextern "C" void findpc(intptr_t x); 482130561Sobrien 483130561Sobrien#endif // !PRODUCT 484130561Sobrien 485130561Sobrienextern "C" void ps() { // print stack 486130561Sobrien if (Thread::current() == NULL) return; 487130561Sobrien Command c("ps"); 488130561Sobrien 489130561Sobrien 490130561Sobrien // Prints the stack of the current Java thread 491130561Sobrien JavaThread* p = JavaThread::active(); 492130561Sobrien tty->print(" for thread: "); 493130561Sobrien p->print(); 494130561Sobrien tty->cr(); 495130561Sobrien 496130561Sobrien if (p->has_last_Java_frame()) { 497130561Sobrien // If the last_Java_fp is set we are in C land and 498130561Sobrien // can call the standard stack_trace function. 499130561Sobrien#ifdef PRODUCT 500130561Sobrien p->print_stack(); 501130561Sobrien } else { 502130561Sobrien tty->print_cr("Cannot find the last Java frame, printing stack disabled."); 503130561Sobrien#else // !PRODUCT 504130561Sobrien p->trace_stack(); 505130561Sobrien } else { 506130561Sobrien frame f = os::current_frame(); 507130561Sobrien RegisterMap reg_map(p); 508130561Sobrien f = f.sender(®_map); 509130561Sobrien tty->print("(guessing starting frame id=%#p based on current fp)\n", f.id()); 510130561Sobrien p->trace_stack_from(vframe::new_vframe(&f, ®_map, p)); 511130561Sobrien pd_ps(f); 512130561Sobrien#endif // PRODUCT 513130561Sobrien } 514130561Sobrien 515130561Sobrien} 516130561Sobrien 517130561Sobrienextern "C" void pfl() { 518130561Sobrien // print frame layout 519130561Sobrien Command c("pfl"); 520130561Sobrien JavaThread* p = JavaThread::active(); 521130561Sobrien tty->print(" for thread: "); 522130561Sobrien p->print(); 523130561Sobrien tty->cr(); 524130561Sobrien if (p->has_last_Java_frame()) { 525130561Sobrien p->print_frame_layout(); 526130561Sobrien } 527130561Sobrien} 528130561Sobrien 529130561Sobrien#ifndef PRODUCT 530130561Sobrien 531130561Sobrienextern "C" void psf() { // print stack frames 532130561Sobrien { 533130561Sobrien Command c("psf"); 534130561Sobrien JavaThread* p = JavaThread::active(); 535130561Sobrien tty->print(" for thread: "); 536130561Sobrien p->print(); 537130561Sobrien tty->cr(); 538130561Sobrien if (p->has_last_Java_frame()) { 539130561Sobrien p->trace_frames(); 540130561Sobrien } 541130561Sobrien } 542130561Sobrien} 543130561Sobrien 544130561Sobrien 545130561Sobrienextern "C" void threads() { 546130561Sobrien Command c("threads"); 547130561Sobrien Threads::print(false, true); 548130561Sobrien} 549130561Sobrien 550130561Sobrien 551130561Sobrienextern "C" void psd() { 552130561Sobrien Command c("psd"); 553130561Sobrien SystemDictionary::print(); 554130561Sobrien} 555130561Sobrien 556130561Sobrien 557130561Sobrienextern "C" void safepoints() { 558130561Sobrien Command c("safepoints"); 559130561Sobrien SafepointSynchronize::print_state(); 560130561Sobrien} 561130561Sobrien 562130561Sobrien#endif // !PRODUCT 563130561Sobrien 564130561Sobrienextern "C" void pss() { // print all stacks 565130561Sobrien if (Thread::current() == NULL) return; 566130561Sobrien Command c("pss"); 567130561Sobrien Threads::print(true, PRODUCT_ONLY(false) NOT_PRODUCT(true)); 568130561Sobrien} 569130561Sobrien 570130561Sobrien#ifndef PRODUCT 571130561Sobrien 572130561Sobrienextern "C" void debug() { // to set things up for compiler debugging 573130561Sobrien Command c("debug"); 574130561Sobrien WizardMode = true; 575130561Sobrien PrintVMMessages = PrintCompilation = true; 576130561Sobrien PrintInlining = PrintAssembly = true; 577130561Sobrien tty->flush(); 578130561Sobrien} 579130561Sobrien 580130561Sobrien 581130561Sobrienextern "C" void ndebug() { // undo debug() 582130561Sobrien Command c("ndebug"); 583130561Sobrien PrintCompilation = false; 584130561Sobrien PrintInlining = PrintAssembly = false; 585130561Sobrien tty->flush(); 586130561Sobrien} 587130561Sobrien 588130561Sobrien 589130561Sobrienextern "C" void flush() { 590130561Sobrien Command c("flush"); 591130561Sobrien tty->flush(); 592130561Sobrien} 593130561Sobrien 594130561Sobrienextern "C" void events() { 595130561Sobrien Command c("events"); 596130561Sobrien Events::print(); 597130561Sobrien} 598130561Sobrien 599130561Sobrienextern "C" Method* findm(intptr_t pc) { 600130561Sobrien Command c("findm"); 601130561Sobrien nmethod* nm = CodeCache::find_nmethod((address)pc); 602130561Sobrien return (nm == NULL) ? (Method*)NULL : nm->method(); 603130561Sobrien} 604130561Sobrien 605130561Sobrien 606130561Sobrienextern "C" nmethod* findnm(intptr_t addr) { 607130561Sobrien Command c("findnm"); 608130561Sobrien return CodeCache::find_nmethod((address)addr); 609130561Sobrien} 610130561Sobrien 611130561Sobrien// Another interface that isn't ambiguous in dbx. 612130561Sobrien// Can we someday rename the other find to hsfind? 613130561Sobrienextern "C" void hsfind(intptr_t x) { 614130561Sobrien Command c("hsfind"); 615130561Sobrien os::print_location(tty, x, false); 616130561Sobrien} 617130561Sobrien 618130561Sobrien 619130561Sobrienextern "C" void find(intptr_t x) { 620130561Sobrien Command c("find"); 621130561Sobrien os::print_location(tty, x, false); 622130561Sobrien} 623130561Sobrien 624130561Sobrien 625130561Sobrienextern "C" void findpc(intptr_t x) { 626130561Sobrien Command c("findpc"); 627130561Sobrien os::print_location(tty, x, true); 628130561Sobrien} 629130561Sobrien 630130561Sobrien 631130561Sobrien// Need method pointer to find bcp, when not in permgen. 632130561Sobrienextern "C" void findbcp(intptr_t method, intptr_t bcp) { 633130561Sobrien Command c("findbcp"); 634130561Sobrien Method* mh = (Method*)method; 635130561Sobrien if (!mh->is_native()) { 636130561Sobrien tty->print_cr("bci_from(%p) = %d; print_codes():", 637130561Sobrien mh, mh->bci_from(address(bcp))); 638130561Sobrien mh->print_codes_on(tty); 639130561Sobrien } 640130561Sobrien} 641130561Sobrien 642130561Sobrien// int versions of all methods to avoid having to type type casts in the debugger 643130561Sobrien 644130561Sobrienvoid pp(intptr_t p) { pp((void*)p); } 645130561Sobrienvoid pp(oop p) { pp((void*)p); } 646130561Sobrien 647130561Sobrienvoid help() { 648130561Sobrien Command c("help"); 649130561Sobrien tty->print_cr("basic"); 650130561Sobrien tty->print_cr(" pp(void* p) - try to make sense of p"); 651130561Sobrien tty->print_cr(" pv(intptr_t p)- ((PrintableResourceObj*) p)->print()"); 652130561Sobrien tty->print_cr(" ps() - print current thread stack"); 653130561Sobrien tty->print_cr(" pss() - print all thread stacks"); 654130561Sobrien tty->print_cr(" pm(int pc) - print Method* given compiled PC"); 655130561Sobrien tty->print_cr(" findm(intptr_t pc) - finds Method*"); 656130561Sobrien tty->print_cr(" find(intptr_t x) - finds & prints nmethod/stub/bytecode/oop based on pointer into it"); 657130561Sobrien 658130561Sobrien tty->print_cr("misc."); 659130561Sobrien tty->print_cr(" flush() - flushes the log file"); 660130561Sobrien tty->print_cr(" events() - dump events from ring buffers"); 661130561Sobrien 662130561Sobrien 663130561Sobrien tty->print_cr("compiler debugging"); 664130561Sobrien tty->print_cr(" debug() - to set things up for compiler debugging"); 665130561Sobrien tty->print_cr(" ndebug() - undo debug"); 666130561Sobrien} 667130561Sobrien 668130561Sobrien#if 0 669130561Sobrien 670130561Sobrien// BobV's command parser for debugging on windows when nothing else works. 671130561Sobrien 672130561Sobrienenum CommandID { 673130561Sobrien CMDID_HELP, 674130561Sobrien CMDID_QUIT, 675130561Sobrien CMDID_HSFIND, 676130561Sobrien CMDID_PSS, 677130561Sobrien CMDID_PS, 678130561Sobrien CMDID_PSF, 679130561Sobrien CMDID_FINDM, 680130561Sobrien CMDID_FINDNM, 681130561Sobrien CMDID_PP, 682130561Sobrien CMDID_BPT, 683130561Sobrien CMDID_EXIT, 684130561Sobrien CMDID_VERIFY, 685130561Sobrien CMDID_THREADS, 686130561Sobrien CMDID_ILLEGAL = 99 687130561Sobrien}; 688130561Sobrien 689130561Sobrienstruct CommandParser { 690130561Sobrien char *name; 691130561Sobrien CommandID code; 692130561Sobrien char *description; 693130561Sobrien}; 694130561Sobrien 695130561Sobrienstruct CommandParser CommandList[] = { 696130561Sobrien (char *)"help", CMDID_HELP, " Dump this list", 697130561Sobrien (char *)"quit", CMDID_QUIT, " Return from this routine", 698130561Sobrien (char *)"hsfind", CMDID_HSFIND, "Perform an hsfind on an address", 699130561Sobrien (char *)"ps", CMDID_PS, " Print Current Thread Stack Trace", 700130561Sobrien (char *)"pss", CMDID_PSS, " Print All Thread Stack Trace", 701130561Sobrien (char *)"psf", CMDID_PSF, " Print All Stack Frames", 702130561Sobrien (char *)"findm", CMDID_FINDM, " Find a Method* from a PC", 703130561Sobrien (char *)"findnm", CMDID_FINDNM, "Find an nmethod from a PC", 704130561Sobrien (char *)"pp", CMDID_PP, " Find out something about a pointer", 705130561Sobrien (char *)"break", CMDID_BPT, " Execute a breakpoint", 706130561Sobrien (char *)"exitvm", CMDID_EXIT, "Exit the VM", 707130561Sobrien (char *)"verify", CMDID_VERIFY, "Perform a Heap Verify", 708130561Sobrien (char *)"thread", CMDID_THREADS, "Dump Info on all Threads", 709130561Sobrien (char *)0, CMDID_ILLEGAL 710130561Sobrien}; 711130561Sobrien 712130561Sobrien 713130561Sobrien// get_debug_command() 714130561Sobrien// 715130561Sobrien// Read a command from standard input. 716130561Sobrien// This is useful when you have a debugger 717130561Sobrien// which doesn't support calling into functions. 718130561Sobrien// 719130561Sobrienvoid get_debug_command() 720130561Sobrien{ 721130561Sobrien ssize_t count; 722130561Sobrien int i,j; 723130561Sobrien bool gotcommand; 724130561Sobrien intptr_t addr; 725130561Sobrien char buffer[256]; 726130561Sobrien nmethod *nm; 727130561Sobrien Method* m; 728130561Sobrien 729130561Sobrien tty->print_cr("You have entered the diagnostic command interpreter"); 730130561Sobrien tty->print("The supported commands are:\n"); 731130561Sobrien for ( i=0; ; i++ ) { 732130561Sobrien if ( CommandList[i].code == CMDID_ILLEGAL ) 733130561Sobrien break; 734130561Sobrien tty->print_cr(" %s \n", CommandList[i].name ); 735130561Sobrien } 736130561Sobrien 737130561Sobrien while ( 1 ) { 738130561Sobrien gotcommand = false; 739130561Sobrien tty->print("Please enter a command: "); 740130561Sobrien count = scanf("%s", buffer) ; 741130561Sobrien if ( count >=0 ) { 742130561Sobrien for ( i=0; ; i++ ) { 743130561Sobrien if ( CommandList[i].code == CMDID_ILLEGAL ) { 744130561Sobrien if (!gotcommand) tty->print("Invalid command, please try again\n"); 745130561Sobrien break; 746130561Sobrien } 747130561Sobrien if ( strcmp(buffer, CommandList[i].name) == 0 ) { 748130561Sobrien gotcommand = true; 749130561Sobrien switch ( CommandList[i].code ) { 750130561Sobrien case CMDID_PS: 751130561Sobrien ps(); 752130561Sobrien break; 753130561Sobrien case CMDID_PSS: 754130561Sobrien pss(); 755130561Sobrien break; 756130561Sobrien case CMDID_PSF: 757130561Sobrien psf(); 758130561Sobrien break; 759130561Sobrien case CMDID_FINDM: 760130561Sobrien tty->print("Please enter the hex addr to pass to findm: "); 761130561Sobrien scanf("%I64X", &addr); 762130561Sobrien m = (Method*)findm(addr); 763130561Sobrien tty->print("findm(0x%I64X) returned 0x%I64X\n", addr, m); 764130561Sobrien break; 765130561Sobrien case CMDID_FINDNM: 766130561Sobrien tty->print("Please enter the hex addr to pass to findnm: "); 767130561Sobrien scanf("%I64X", &addr); 768130561Sobrien nm = (nmethod*)findnm(addr); 769130561Sobrien tty->print("findnm(0x%I64X) returned 0x%I64X\n", addr, nm); 770130561Sobrien break; 771130561Sobrien case CMDID_PP: 772130561Sobrien tty->print("Please enter the hex addr to pass to pp: "); 773130561Sobrien scanf("%I64X", &addr); 774130561Sobrien pp((void*)addr); 775130561Sobrien break; 776130561Sobrien case CMDID_EXIT: 777130561Sobrien exit(0); 778130561Sobrien case CMDID_HELP: 779130561Sobrien tty->print("Here are the supported commands: "); 780130561Sobrien for ( j=0; ; j++ ) { 781130561Sobrien if ( CommandList[j].code == CMDID_ILLEGAL ) 782130561Sobrien break; 783130561Sobrien tty->print_cr(" %s -- %s\n", CommandList[j].name, 784130561Sobrien CommandList[j].description ); 785130561Sobrien } 786130561Sobrien break; 787130561Sobrien case CMDID_QUIT: 788130561Sobrien return; 789130561Sobrien break; 790130561Sobrien case CMDID_BPT: 791130561Sobrien BREAKPOINT; 792130561Sobrien break; 793130561Sobrien case CMDID_VERIFY: 794130561Sobrien verify();; 795130561Sobrien break; 796130561Sobrien case CMDID_THREADS: 797130561Sobrien threads();; 798130561Sobrien break; 799130561Sobrien case CMDID_HSFIND: 800130561Sobrien tty->print("Please enter the hex addr to pass to hsfind: "); 801130561Sobrien scanf("%I64X", &addr); 802130561Sobrien tty->print("Calling hsfind(0x%I64X)\n", addr); 803130561Sobrien hsfind(addr); 804130561Sobrien break; 805130561Sobrien default: 806130561Sobrien case CMDID_ILLEGAL: 807130561Sobrien break; 808130561Sobrien } 809130561Sobrien } 810130561Sobrien } 811130561Sobrien } 812130561Sobrien } 813130561Sobrien} 814130561Sobrien#endif 815130561Sobrien 816130561Sobrien#endif // !PRODUCT 817130561Sobrien