debug.cpp revision 1915:2f644f85485d
1216295Ssyrinx/* 2216295Ssyrinx * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. 3216295Ssyrinx * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4216295Ssyrinx * 5216295Ssyrinx * This code is free software; you can redistribute it and/or modify it 6216295Ssyrinx * under the terms of the GNU General Public License version 2 only, as 7216295Ssyrinx * published by the Free Software Foundation. 8216295Ssyrinx * 9216295Ssyrinx * This code is distributed in the hope that it will be useful, but WITHOUT 10216295Ssyrinx * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11216295Ssyrinx * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12216295Ssyrinx * version 2 for more details (a copy is included in the LICENSE file that 13216295Ssyrinx * accompanied this code). 14216295Ssyrinx * 15216295Ssyrinx * You should have received a copy of the GNU General Public License version 16216295Ssyrinx * 2 along with this work; if not, write to the Free Software Foundation, 17216295Ssyrinx * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18216295Ssyrinx * 19216295Ssyrinx * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20216295Ssyrinx * or visit www.oracle.com if you need additional information or have any 21216295Ssyrinx * questions. 22216295Ssyrinx * 23216295Ssyrinx */ 24216295Ssyrinx 25216295Ssyrinx#include "precompiled.hpp" 26216295Ssyrinx#include "classfile/systemDictionary.hpp" 27216295Ssyrinx#include "code/codeCache.hpp" 28216295Ssyrinx#include "code/icBuffer.hpp" 29216295Ssyrinx#include "code/nmethod.hpp" 30216295Ssyrinx#include "code/vtableStubs.hpp" 31216295Ssyrinx#include "compiler/compileBroker.hpp" 32216295Ssyrinx#include "compiler/disassembler.hpp" 33216295Ssyrinx#include "gc_implementation/shared/markSweep.hpp" 34216295Ssyrinx#include "gc_interface/collectedHeap.hpp" 35216295Ssyrinx#include "interpreter/bytecodeHistogram.hpp" 36216295Ssyrinx#include "interpreter/interpreter.hpp" 37216295Ssyrinx#include "memory/resourceArea.hpp" 38216295Ssyrinx#include "memory/universe.hpp" 39216295Ssyrinx#include "oops/oop.inline.hpp" 40216295Ssyrinx#include "prims/privilegedStack.hpp" 41216295Ssyrinx#include "runtime/arguments.hpp" 42216295Ssyrinx#include "runtime/frame.hpp" 43216295Ssyrinx#include "runtime/java.hpp" 44216295Ssyrinx#include "runtime/sharedRuntime.hpp" 45216295Ssyrinx#include "runtime/stubCodeGenerator.hpp" 46216295Ssyrinx#include "runtime/stubRoutines.hpp" 47216295Ssyrinx#include "runtime/vframe.hpp" 48216295Ssyrinx#include "services/heapDumper.hpp" 49216295Ssyrinx#include "utilities/defaultStream.hpp" 50216295Ssyrinx#include "utilities/events.hpp" 51216295Ssyrinx#include "utilities/top.hpp" 52216295Ssyrinx#include "utilities/vmError.hpp" 53216295Ssyrinx#ifdef TARGET_OS_FAMILY_linux 54216295Ssyrinx# include "os_linux.inline.hpp" 55216295Ssyrinx# include "thread_linux.inline.hpp" 56216295Ssyrinx#endif 57216295Ssyrinx#ifdef TARGET_OS_FAMILY_solaris 58216295Ssyrinx# include "os_solaris.inline.hpp" 59216295Ssyrinx# include "thread_solaris.inline.hpp" 60216295Ssyrinx#endif 61216295Ssyrinx#ifdef TARGET_OS_FAMILY_windows 62216295Ssyrinx# include "os_windows.inline.hpp" 63216295Ssyrinx# include "thread_windows.inline.hpp" 64216295Ssyrinx#endif 65216295Ssyrinx 66216295Ssyrinx#ifndef ASSERT 67216295Ssyrinx# ifdef _DEBUG 68216295Ssyrinx // NOTE: don't turn the lines below into a comment -- if you're getting 69216295Ssyrinx // a compile error here, change the settings to define ASSERT 70216295Ssyrinx ASSERT should be defined when _DEBUG is defined. It is not intended to be used for debugging 71216295Ssyrinx functions that do not slow down the system too much and thus can be left in optimized code. 72216295Ssyrinx On the other hand, the code should not be included in a production version. 73216295Ssyrinx# endif // _DEBUG 74216295Ssyrinx#endif // ASSERT 75216295Ssyrinx 76216295Ssyrinx 77216295Ssyrinx#ifdef _DEBUG 78216295Ssyrinx# ifndef ASSERT 79229933Ssyrinx configuration error: ASSERT must be defined in debug version 80229933Ssyrinx# endif // ASSERT 81229933Ssyrinx#endif // _DEBUG 82216295Ssyrinx 83216295Ssyrinx 84216295Ssyrinx#ifdef PRODUCT 85216295Ssyrinx# if -defined _DEBUG || -defined ASSERT 86216295Ssyrinx configuration error: ASSERT et al. must not be defined in PRODUCT version 87216295Ssyrinx# endif 88216295Ssyrinx#endif // PRODUCT 89216295Ssyrinx 90216295Ssyrinx 91216295Ssyrinxvoid warning(const char* format, ...) { 92216295Ssyrinx if (PrintWarnings) { 93216295Ssyrinx // In case error happens before init or during shutdown 94216295Ssyrinx if (tty == NULL) ostream_init(); 95216295Ssyrinx 96216295Ssyrinx tty->print("%s warning: ", VM_Version::vm_name()); 97216295Ssyrinx va_list ap; 98216295Ssyrinx va_start(ap, format); 99216295Ssyrinx tty->vprint_cr(format, ap); 100216295Ssyrinx va_end(ap); 101216295Ssyrinx } 102216295Ssyrinx if (BreakAtWarning) BREAKPOINT; 103216295Ssyrinx} 104216295Ssyrinx 105216295Ssyrinx#ifndef PRODUCT 106216295Ssyrinx 107216295Ssyrinx#define is_token_break(ch) (isspace(ch) || (ch) == ',') 108216295Ssyrinx 109216295Ssyrinxstatic const char* last_file_name = NULL; 110216295Ssyrinxstatic int last_line_no = -1; 111216295Ssyrinx 112216295Ssyrinx// assert/guarantee/... may happen very early during VM initialization. 113216295Ssyrinx// Don't rely on anything that is initialized by Threads::create_vm(). For 114216295Ssyrinx// example, don't use tty. 115216295Ssyrinxbool error_is_suppressed(const char* file_name, int line_no) { 116216295Ssyrinx // The following 1-element cache requires that passed-in 117216295Ssyrinx // file names are always only constant literals. 118216295Ssyrinx if (file_name == last_file_name && line_no == last_line_no) return true; 119216295Ssyrinx 120216295Ssyrinx int file_name_len = (int)strlen(file_name); 121216295Ssyrinx char separator = os::file_separator()[0]; 122216295Ssyrinx const char* base_name = strrchr(file_name, separator); 123216295Ssyrinx if (base_name == NULL) 124216295Ssyrinx base_name = file_name; 125216295Ssyrinx 126216295Ssyrinx // scan the SuppressErrorAt option 127216295Ssyrinx const char* cp = SuppressErrorAt; 128216295Ssyrinx for (;;) { 129216295Ssyrinx const char* sfile; 130216295Ssyrinx int sfile_len; 131216295Ssyrinx int sline; 132216295Ssyrinx bool noisy; 133216295Ssyrinx while ((*cp) != '\0' && is_token_break(*cp)) cp++; 134216295Ssyrinx if ((*cp) == '\0') break; 135216295Ssyrinx sfile = cp; 136216295Ssyrinx while ((*cp) != '\0' && !is_token_break(*cp) && (*cp) != ':') cp++; 137216295Ssyrinx sfile_len = cp - sfile; 138216295Ssyrinx if ((*cp) == ':') cp++; 139216295Ssyrinx sline = 0; 140216295Ssyrinx while ((*cp) != '\0' && isdigit(*cp)) { 141216295Ssyrinx sline *= 10; 142216295Ssyrinx sline += (*cp) - '0'; 143216295Ssyrinx cp++; 144216295Ssyrinx } 145216295Ssyrinx // "file:line!" means the assert suppression is not silent 146216295Ssyrinx noisy = ((*cp) == '!'); 147216295Ssyrinx while ((*cp) != '\0' && !is_token_break(*cp)) cp++; 148216295Ssyrinx // match the line 149216295Ssyrinx if (sline != 0) { 150216295Ssyrinx if (sline != line_no) continue; 151216295Ssyrinx } 152216295Ssyrinx // match the file 153216295Ssyrinx if (sfile_len > 0) { 154229933Ssyrinx const char* look = file_name; 155216295Ssyrinx const char* look_max = file_name + file_name_len - sfile_len; 156216295Ssyrinx const char* foundp; 157216295Ssyrinx bool match = false; 158216295Ssyrinx while (!match 159216295Ssyrinx && (foundp = strchr(look, sfile[0])) != NULL 160216295Ssyrinx && foundp <= look_max) { 161216295Ssyrinx match = true; 162216295Ssyrinx for (int i = 1; i < sfile_len; i++) { 163216295Ssyrinx if (sfile[i] != foundp[i]) { 164216295Ssyrinx match = false; 165216295Ssyrinx break; 166216295Ssyrinx } 167216295Ssyrinx } 168216295Ssyrinx look = foundp + 1; 169216295Ssyrinx } 170216295Ssyrinx if (!match) continue; 171216295Ssyrinx } 172216295Ssyrinx // got a match! 173216295Ssyrinx if (noisy) { 174216295Ssyrinx fdStream out(defaultStream::output_fd()); 175216295Ssyrinx out.print_raw("[error suppressed at "); 176216295Ssyrinx out.print_raw(base_name); 177216295Ssyrinx char buf[16]; 178216295Ssyrinx jio_snprintf(buf, sizeof(buf), ":%d]", line_no); 179216295Ssyrinx out.print_raw_cr(buf); 180216295Ssyrinx } else { 181216295Ssyrinx // update 1-element cache for fast silent matches 182216295Ssyrinx last_file_name = file_name; 183216295Ssyrinx last_line_no = line_no; 184216295Ssyrinx } 185216295Ssyrinx return true; 186216295Ssyrinx } 187216295Ssyrinx 188216295Ssyrinx if (!is_error_reported()) { 189216295Ssyrinx // print a friendly hint: 190216295Ssyrinx fdStream out(defaultStream::output_fd()); 191216295Ssyrinx out.print_raw_cr("# To suppress the following error report, specify this argument"); 192216295Ssyrinx out.print_raw ("# after -XX: or in .hotspotrc: SuppressErrorAt="); 193216295Ssyrinx out.print_raw (base_name); 194216295Ssyrinx char buf[16]; 195216295Ssyrinx jio_snprintf(buf, sizeof(buf), ":%d", line_no); 196216295Ssyrinx out.print_raw_cr(buf); 197216295Ssyrinx } 198216295Ssyrinx return false; 199216295Ssyrinx} 200216295Ssyrinx 201216295Ssyrinx#undef is_token_break 202216295Ssyrinx 203216295Ssyrinx#else 204216295Ssyrinx 205216295Ssyrinx// Place-holder for non-existent suppression check: 206216295Ssyrinx#define error_is_suppressed(file_name, line_no) (false) 207216295Ssyrinx 208216295Ssyrinx#endif //PRODUCT 209216295Ssyrinx 210216295Ssyrinxvoid report_vm_error(const char* file, int line, const char* error_msg, 211216295Ssyrinx const char* detail_msg) 212216295Ssyrinx{ 213216295Ssyrinx if (Debugging || error_is_suppressed(file, line)) return; 214216295Ssyrinx Thread* const thread = ThreadLocalStorage::get_thread_slow(); 215216295Ssyrinx VMError err(thread, file, line, error_msg, detail_msg); 216216295Ssyrinx err.report_and_die(); 217216295Ssyrinx} 218216295Ssyrinx 219216295Ssyrinxvoid report_fatal(const char* file, int line, const char* message) 220216295Ssyrinx{ 221216295Ssyrinx report_vm_error(file, line, "fatal error", message); 222216295Ssyrinx} 223216295Ssyrinx 224216295Ssyrinx// Used by report_vm_out_of_memory to detect recursion. 225216295Ssyrinxstatic jint _exiting_out_of_mem = 0; 226216295Ssyrinx 227216295Ssyrinxvoid report_vm_out_of_memory(const char* file, int line, size_t size, 228216295Ssyrinx const char* message) { 229216295Ssyrinx if (Debugging || error_is_suppressed(file, line)) return; 230216295Ssyrinx 231216295Ssyrinx // We try to gather additional information for the first out of memory 232216295Ssyrinx // error only; gathering additional data might cause an allocation and a 233216295Ssyrinx // recursive out_of_memory condition. 234216295Ssyrinx 235216295Ssyrinx const jint exiting = 1; 236216295Ssyrinx // If we succeed in changing the value, we're the first one in. 237216295Ssyrinx bool first_time_here = Atomic::xchg(exiting, &_exiting_out_of_mem) != exiting; 238216295Ssyrinx 239216295Ssyrinx if (first_time_here) { 240216295Ssyrinx Thread* thread = ThreadLocalStorage::get_thread_slow(); 241216295Ssyrinx VMError(thread, file, line, size, message).report_and_die(); 242216295Ssyrinx } 243216295Ssyrinx 244216295Ssyrinx // Dump core and abort 245216295Ssyrinx vm_abort(true); 246216295Ssyrinx} 247216295Ssyrinx 248216295Ssyrinxvoid report_should_not_call(const char* file, int line) { 249216295Ssyrinx report_vm_error(file, line, "ShouldNotCall()"); 250216295Ssyrinx} 251216295Ssyrinx 252228990Suqsvoid report_should_not_reach_here(const char* file, int line) { 253216295Ssyrinx report_vm_error(file, line, "ShouldNotReachHere()"); 254228990Suqs} 255216295Ssyrinx 256216295Ssyrinxvoid report_unimplemented(const char* file, int line) { 257216295Ssyrinx report_vm_error(file, line, "Unimplemented()"); 258216295Ssyrinx} 259216295Ssyrinx 260216295Ssyrinxvoid report_untested(const char* file, int line, const char* message) { 261216295Ssyrinx#ifndef PRODUCT 262216295Ssyrinx warning("Untested: %s in %s: %d\n", message, file, line); 263216295Ssyrinx#endif // PRODUCT 264216295Ssyrinx} 265216295Ssyrinx 266216295Ssyrinxvoid report_java_out_of_memory(const char* message) { 267216295Ssyrinx static jint out_of_memory_reported = 0; 268216295Ssyrinx 269216295Ssyrinx // A number of threads may attempt to report OutOfMemoryError at around the 270216295Ssyrinx // same time. To avoid dumping the heap or executing the data collection 271216295Ssyrinx // commands multiple times we just do it once when the first threads reports 272216295Ssyrinx // the error. 273216295Ssyrinx if (Atomic::cmpxchg(1, &out_of_memory_reported, 0) == 0) { 274216295Ssyrinx // create heap dump before OnOutOfMemoryError commands are executed 275216295Ssyrinx if (HeapDumpOnOutOfMemoryError) { 276216295Ssyrinx tty->print_cr("java.lang.OutOfMemoryError: %s", message); 277216295Ssyrinx HeapDumper::dump_heap_from_oome(); 278216295Ssyrinx } 279216295Ssyrinx 280216295Ssyrinx if (OnOutOfMemoryError && OnOutOfMemoryError[0]) { 281216295Ssyrinx VMError err(message); 282216295Ssyrinx err.report_java_out_of_memory(); 283216295Ssyrinx } 284216295Ssyrinx } 285216295Ssyrinx} 286216295Ssyrinx 287216295Ssyrinx 288216295Ssyrinxextern "C" void ps(); 289216295Ssyrinx 290216295Ssyrinxstatic bool error_reported = false; 291216295Ssyrinx 292216295Ssyrinx// call this when the VM is dying--it might loosen some asserts 293216295Ssyrinxvoid set_error_reported() { 294216295Ssyrinx error_reported = true; 295216295Ssyrinx} 296216295Ssyrinx 297216295Ssyrinxbool is_error_reported() { 298216295Ssyrinx return error_reported; 299216295Ssyrinx} 300216295Ssyrinx 301216295Ssyrinx#ifndef PRODUCT 302216295Ssyrinx#include <signal.h> 303216295Ssyrinx 304216295Ssyrinxvoid test_error_handler(size_t test_num) 305216295Ssyrinx{ 306216295Ssyrinx if (test_num == 0) return; 307216295Ssyrinx 308216295Ssyrinx // If asserts are disabled, use the corresponding guarantee instead. 309216295Ssyrinx size_t n = test_num; 310216295Ssyrinx NOT_DEBUG(if (n <= 2) n += 2); 311216295Ssyrinx 312216295Ssyrinx const char* const str = "hello"; 313216295Ssyrinx const size_t num = (size_t)os::vm_page_size(); 314216295Ssyrinx 315216295Ssyrinx const char* const eol = os::line_separator(); 316216295Ssyrinx const char* const msg = "this message should be truncated during formatting"; 317216295Ssyrinx 318216295Ssyrinx // Keep this in sync with test/runtime/6888954/vmerrors.sh. 319216295Ssyrinx switch (n) { 320216295Ssyrinx case 1: assert(str == NULL, "expected null"); 321216295Ssyrinx case 2: assert(num == 1023 && *str == 'X', 322216295Ssyrinx err_msg("num=" SIZE_FORMAT " str=\"%s\"", num, str)); 323216295Ssyrinx case 3: guarantee(str == NULL, "expected null"); 324216295Ssyrinx case 4: guarantee(num == 1023 && *str == 'X', 325216295Ssyrinx err_msg("num=" SIZE_FORMAT " str=\"%s\"", num, str)); 326216295Ssyrinx case 5: fatal("expected null"); 327216295Ssyrinx case 6: fatal(err_msg("num=" SIZE_FORMAT " str=\"%s\"", num, str)); 328216295Ssyrinx case 7: fatal(err_msg("%s%s# %s%s# %s%s# %s%s# %s%s# " 329216295Ssyrinx "%s%s# %s%s# %s%s# %s%s# %s%s# " 330216295Ssyrinx "%s%s# %s%s# %s%s# %s%s# %s", 331216295Ssyrinx msg, eol, msg, eol, msg, eol, msg, eol, msg, eol, 332216295Ssyrinx msg, eol, msg, eol, msg, eol, msg, eol, msg, eol, 333216295Ssyrinx msg, eol, msg, eol, msg, eol, msg, eol, msg)); 334216295Ssyrinx case 8: vm_exit_out_of_memory(num, "ChunkPool::allocate"); 335216295Ssyrinx case 9: ShouldNotCallThis(); 336216295Ssyrinx case 10: ShouldNotReachHere(); 337216295Ssyrinx case 11: Unimplemented(); 338216295Ssyrinx // This is last because it does not generate an hs_err* file on Windows. 339216295Ssyrinx case 12: os::signal_raise(SIGSEGV); 340216295Ssyrinx 341216295Ssyrinx default: ShouldNotReachHere(); 342216295Ssyrinx } 343216295Ssyrinx} 344216295Ssyrinx#endif // #ifndef PRODUCT 345216295Ssyrinx 346216295Ssyrinx// ------ helper functions for debugging go here ------------ 347216295Ssyrinx 348216295Ssyrinx#ifndef PRODUCT 349216295Ssyrinx// All debug entries should be wrapped with a stack allocated 350216295Ssyrinx// Command object. It makes sure a resource mark is set and 351216295Ssyrinx// flushes the logfile to prevent file sharing problems. 352216295Ssyrinx 353216295Ssyrinxclass Command : public StackObj { 354216295Ssyrinx private: 355216295Ssyrinx ResourceMark rm; 356216295Ssyrinx ResetNoHandleMark rnhm; 357216295Ssyrinx HandleMark hm; 358216295Ssyrinx bool debug_save; 359216295Ssyrinx public: 360216295Ssyrinx static int level; 361216295Ssyrinx Command(const char* str) { 362216295Ssyrinx debug_save = Debugging; 363216295Ssyrinx Debugging = true; 364216295Ssyrinx if (level++ > 0) return; 365216295Ssyrinx tty->cr(); 366216295Ssyrinx tty->print_cr("\"Executing %s\"", str); 367216295Ssyrinx } 368216295Ssyrinx 369216295Ssyrinx ~Command() { tty->flush(); Debugging = debug_save; level--; } 370216295Ssyrinx}; 371216295Ssyrinx 372216295Ssyrinxint Command::level = 0; 373216295Ssyrinx 374216295Ssyrinxextern "C" void blob(CodeBlob* cb) { 375216295Ssyrinx Command c("blob"); 376216295Ssyrinx cb->print(); 377216295Ssyrinx} 378216295Ssyrinx 379216295Ssyrinx 380216295Ssyrinxextern "C" void dump_vtable(address p) { 381216295Ssyrinx Command c("dump_vtable"); 382216295Ssyrinx klassOop k = (klassOop)p; 383216295Ssyrinx instanceKlass::cast(k)->vtable()->print(); 384216295Ssyrinx} 385216295Ssyrinx 386216295Ssyrinx 387216295Ssyrinxextern "C" void nm(intptr_t p) { 388216295Ssyrinx // Actually we look through all CodeBlobs (the nm name has been kept for backwards compatability) 389216295Ssyrinx Command c("nm"); 390216295Ssyrinx CodeBlob* cb = CodeCache::find_blob((address)p); 391216295Ssyrinx if (cb == NULL) { 392216295Ssyrinx tty->print_cr("NULL"); 393216295Ssyrinx } else { 394216295Ssyrinx cb->print(); 395216295Ssyrinx } 396216295Ssyrinx} 397311594Sngie 398216295Ssyrinx 399216295Ssyrinxextern "C" void disnm(intptr_t p) { 400216295Ssyrinx Command c("disnm"); 401216295Ssyrinx CodeBlob* cb = CodeCache::find_blob((address) p); 402229933Ssyrinx nmethod* nm = cb->as_nmethod_or_null(); 403312049Sngie if (nm) { 404216295Ssyrinx nm->print(); 405216295Ssyrinx Disassembler::decode(nm); 406216295Ssyrinx } else { 407216295Ssyrinx cb->print(); 408216295Ssyrinx Disassembler::decode(cb); 409312049Sngie } 410312049Sngie} 411216295Ssyrinx 412312049Sngie 413216295Ssyrinxextern "C" void printnm(intptr_t p) { 414216295Ssyrinx char buffer[256]; 415216295Ssyrinx sprintf(buffer, "printnm: " INTPTR_FORMAT, p); 416216295Ssyrinx Command c(buffer); 417216295Ssyrinx CodeBlob* cb = CodeCache::find_blob((address) p); 418216295Ssyrinx if (cb->is_nmethod()) { 419216295Ssyrinx nmethod* nm = (nmethod*)cb; 420312049Sngie nm->print_nmethod(true); 421312049Sngie } 422216295Ssyrinx} 423312049Sngie 424216295Ssyrinx 425216295Ssyrinxextern "C" void universe() { 426216295Ssyrinx Command c("universe"); 427216295Ssyrinx Universe::print(); 428216295Ssyrinx} 429216295Ssyrinx 430312049Sngie 431216295Ssyrinxextern "C" void verify() { 432216295Ssyrinx // try to run a verify on the entire system 433216295Ssyrinx // note: this may not be safe if we're not at a safepoint; for debugging, 434216295Ssyrinx // this manipulates the safepoint settings to avoid assertion failures 435216295Ssyrinx Command c("universe verify"); 436216295Ssyrinx bool safe = SafepointSynchronize::is_at_safepoint(); 437216295Ssyrinx if (!safe) { 438216295Ssyrinx tty->print_cr("warning: not at safepoint -- verify may fail"); 439216295Ssyrinx SafepointSynchronize::set_is_at_safepoint(); 440216295Ssyrinx } 441216295Ssyrinx // Ensure Eden top is correct before verification 442216295Ssyrinx Universe::heap()->prepare_for_verify(); 443216295Ssyrinx Universe::verify(true); 444216295Ssyrinx if (!safe) SafepointSynchronize::set_is_not_at_safepoint(); 445216295Ssyrinx} 446216295Ssyrinx 447216295Ssyrinx 448216295Ssyrinxextern "C" void pp(void* p) { 449216295Ssyrinx Command c("pp"); 450216295Ssyrinx FlagSetting fl(PrintVMMessages, true); 451216295Ssyrinx if (Universe::heap()->is_in(p)) { 452216295Ssyrinx oop obj = oop(p); 453216295Ssyrinx obj->print(); 454216295Ssyrinx } else { 455216295Ssyrinx tty->print("%#p", p); 456216295Ssyrinx } 457216295Ssyrinx} 458216295Ssyrinx 459216295Ssyrinx 460216295Ssyrinx// pv: print vm-printable object 461216295Ssyrinxextern "C" void pa(intptr_t p) { ((AllocatedObj*) p)->print(); } 462216295Ssyrinxextern "C" void findpc(intptr_t x); 463216295Ssyrinx 464216295Ssyrinxextern "C" void ps() { // print stack 465216295Ssyrinx Command c("ps"); 466216295Ssyrinx 467228990Suqs 468216295Ssyrinx // Prints the stack of the current Java thread 469229933Ssyrinx JavaThread* p = JavaThread::active(); 470216295Ssyrinx tty->print(" for thread: "); 471229933Ssyrinx p->print(); 472229933Ssyrinx tty->cr(); 473229933Ssyrinx 474229933Ssyrinx if (p->has_last_Java_frame()) { 475216295Ssyrinx // If the last_Java_fp is set we are in C land and 476229933Ssyrinx // can call the standard stack_trace function. 477229933Ssyrinx p->trace_stack(); 478216295Ssyrinx } else { 479216295Ssyrinx frame f = os::current_frame(); 480216295Ssyrinx RegisterMap reg_map(p); 481216295Ssyrinx f = f.sender(®_map); 482216295Ssyrinx tty->print("(guessing starting frame id=%#p based on current fp)\n", f.id()); 483216295Ssyrinx p->trace_stack_from(vframe::new_vframe(&f, ®_map, p)); 484216295Ssyrinx pd_ps(f); 485229933Ssyrinx } 486229933Ssyrinx 487229933Ssyrinx} 488229933Ssyrinx 489216295Ssyrinx 490216295Ssyrinxextern "C" void psf() { // print stack frames 491216295Ssyrinx { 492216295Ssyrinx Command c("psf"); 493216295Ssyrinx JavaThread* p = JavaThread::active(); 494216295Ssyrinx tty->print(" for thread: "); 495216295Ssyrinx p->print(); 496216295Ssyrinx tty->cr(); 497216295Ssyrinx if (p->has_last_Java_frame()) { 498229933Ssyrinx p->trace_frames(); 499229933Ssyrinx } 500216295Ssyrinx } 501229933Ssyrinx} 502216295Ssyrinx 503216295Ssyrinx 504216295Ssyrinxextern "C" void threads() { 505229933Ssyrinx Command c("threads"); 506216295Ssyrinx Threads::print(false, true); 507312049Sngie} 508312049Sngie 509229933Ssyrinx 510312049Sngieextern "C" void psd() { 511229933Ssyrinx Command c("psd"); 512229933Ssyrinx SystemDictionary::print(); 513229933Ssyrinx} 514229933Ssyrinx 515229933Ssyrinx 516229933Ssyrinxextern "C" void safepoints() { 517312049Sngie Command c("safepoints"); 518216295Ssyrinx SafepointSynchronize::print_state(); 519216295Ssyrinx} 520216295Ssyrinx 521216295Ssyrinx 522216295Ssyrinxextern "C" void pss() { // print all stacks 523216295Ssyrinx Command c("pss"); 524312049Sngie Threads::print(true, true); 525216295Ssyrinx} 526216295Ssyrinx 527312049Sngie 528312049Sngieextern "C" void debug() { // to set things up for compiler debugging 529216295Ssyrinx Command c("debug"); 530216295Ssyrinx WizardMode = true; 531311594Sngie PrintVMMessages = PrintCompilation = true; 532216295Ssyrinx PrintInlining = PrintAssembly = true; 533216295Ssyrinx tty->flush(); 534216295Ssyrinx} 535216295Ssyrinx 536216295Ssyrinx 537216295Ssyrinxextern "C" void ndebug() { // undo debug() 538216295Ssyrinx Command c("ndebug"); 539312049Sngie PrintCompilation = false; 540229933Ssyrinx PrintInlining = PrintAssembly = false; 541216295Ssyrinx tty->flush(); 542216295Ssyrinx} 543312049Sngie 544312049Sngie 545216295Ssyrinxextern "C" void flush() { 546216295Ssyrinx Command c("flush"); 547216295Ssyrinx tty->flush(); 548216295Ssyrinx} 549216295Ssyrinx 550216295Ssyrinx 551216295Ssyrinxextern "C" void events() { 552216295Ssyrinx Command c("events"); 553216295Ssyrinx Events::print_last(tty, 50); 554216295Ssyrinx} 555216295Ssyrinx 556216295Ssyrinx 557216295Ssyrinxextern "C" void nevents(int n) { 558216295Ssyrinx Command c("events"); 559216295Ssyrinx Events::print_last(tty, n); 560216295Ssyrinx} 561216295Ssyrinx 562216295Ssyrinx 563216295Ssyrinx// Given a heap address that was valid before the most recent GC, if 564216295Ssyrinx// the oop that used to contain it is still live, prints the new 565216295Ssyrinx// location of the oop and the address. Useful for tracking down 566216295Ssyrinx// certain kinds of naked oop and oop map bugs. 567311594Sngieextern "C" void pnl(intptr_t old_heap_addr) { 568216295Ssyrinx // Print New Location of old heap address 569216295Ssyrinx Command c("pnl"); 570216295Ssyrinx#ifndef VALIDATE_MARK_SWEEP 571216295Ssyrinx tty->print_cr("Requires build with VALIDATE_MARK_SWEEP defined (debug build) and RecordMarkSweepCompaction enabled"); 572216295Ssyrinx#else 573216295Ssyrinx MarkSweep::print_new_location_of_heap_address((HeapWord*) old_heap_addr); 574216295Ssyrinx#endif 575216295Ssyrinx} 576216295Ssyrinx 577216295Ssyrinx 578216295Ssyrinxextern "C" methodOop findm(intptr_t pc) { 579216295Ssyrinx Command c("findm"); 580216295Ssyrinx nmethod* nm = CodeCache::find_nmethod((address)pc); 581216295Ssyrinx return (nm == NULL) ? (methodOop)NULL : nm->method(); 582216295Ssyrinx} 583216295Ssyrinx 584216295Ssyrinx 585216295Ssyrinxextern "C" nmethod* findnm(intptr_t addr) { 586216295Ssyrinx Command c("findnm"); 587216295Ssyrinx return CodeCache::find_nmethod((address)addr); 588216295Ssyrinx} 589216295Ssyrinx 590216295Ssyrinxstatic address same_page(address x, address y) { 591216295Ssyrinx intptr_t page_bits = -os::vm_page_size(); 592216295Ssyrinx if ((intptr_t(x) & page_bits) == (intptr_t(y) & page_bits)) { 593216295Ssyrinx return x; 594216295Ssyrinx } else if (x > y) { 595216295Ssyrinx return (address)(intptr_t(y) | ~page_bits) + 1; 596216295Ssyrinx } else { 597216295Ssyrinx return (address)(intptr_t(y) & page_bits); 598216295Ssyrinx } 599216295Ssyrinx} 600216295Ssyrinx 601216295Ssyrinxclass LookForRefInGenClosure : public OopsInGenClosure { 602216295Ssyrinxpublic: 603216295Ssyrinx oop target; 604216295Ssyrinx void do_oop(oop* o) { 605216295Ssyrinx if (o != NULL && *o == target) { 606216295Ssyrinx tty->print_cr(INTPTR_FORMAT, o); 607216295Ssyrinx } 608216295Ssyrinx } 609216295Ssyrinx void do_oop(narrowOop* o) { ShouldNotReachHere(); } 610216295Ssyrinx}; 611216295Ssyrinx 612216295Ssyrinx 613216295Ssyrinxclass LookForRefInObjectClosure : public ObjectClosure { 614216295Ssyrinxprivate: 615310561Sngie LookForRefInGenClosure look_in_object; 616310561Sngiepublic: 617216295Ssyrinx LookForRefInObjectClosure(oop target) { look_in_object.target = target; } 618216295Ssyrinx void do_object(oop obj) { 619216295Ssyrinx obj->oop_iterate(&look_in_object); 620216295Ssyrinx } 621216295Ssyrinx}; 622216295Ssyrinx 623216295Ssyrinx 624216295Ssyrinxstatic void findref(intptr_t x) { 625216295Ssyrinx CollectedHeap *ch = Universe::heap(); 626216295Ssyrinx LookForRefInGenClosure lookFor; 627216295Ssyrinx lookFor.target = (oop) x; 628216295Ssyrinx LookForRefInObjectClosure look_in_object((oop) x); 629310561Sngie 630216295Ssyrinx tty->print_cr("Searching heap:"); 631216295Ssyrinx ch->object_iterate(&look_in_object); 632216295Ssyrinx 633216295Ssyrinx tty->print_cr("Searching strong roots:"); 634216295Ssyrinx Universe::oops_do(&lookFor, false); 635216295Ssyrinx JNIHandles::oops_do(&lookFor); // Global (strong) JNI handles 636216295Ssyrinx Threads::oops_do(&lookFor, NULL); 637216295Ssyrinx ObjectSynchronizer::oops_do(&lookFor); 638216295Ssyrinx //FlatProfiler::oops_do(&lookFor); 639216295Ssyrinx SystemDictionary::oops_do(&lookFor); 640216295Ssyrinx 641216295Ssyrinx tty->print_cr("Searching code cache:"); 642216295Ssyrinx CodeCache::oops_do(&lookFor); 643216295Ssyrinx 644216295Ssyrinx tty->print_cr("Done."); 645216295Ssyrinx} 646311594Sngie 647216295Ssyrinxclass FindClassObjectClosure: public ObjectClosure { 648216295Ssyrinx private: 649216295Ssyrinx const char* _target; 650216295Ssyrinx public: 651216295Ssyrinx FindClassObjectClosure(const char name[]) { _target = name; } 652216295Ssyrinx 653216295Ssyrinx virtual void do_object(oop obj) { 654216295Ssyrinx if (obj->is_klass()) { 655216295Ssyrinx Klass* k = klassOop(obj)->klass_part(); 656216295Ssyrinx if (k->name() != NULL) { 657216295Ssyrinx ResourceMark rm; 658216295Ssyrinx const char* ext = k->external_name(); 659216295Ssyrinx if ( strcmp(_target, ext) == 0 ) { 660216295Ssyrinx tty->print_cr("Found " INTPTR_FORMAT, obj); 661216295Ssyrinx obj->print(); 662216295Ssyrinx } 663216295Ssyrinx } 664216295Ssyrinx } 665216295Ssyrinx } 666216295Ssyrinx}; 667216295Ssyrinx 668216295Ssyrinx// 669216295Ssyrinxextern "C" void findclass(const char name[]) { 670216295Ssyrinx Command c("findclass"); 671216295Ssyrinx if (name != NULL) { 672216295Ssyrinx tty->print_cr("Finding class %s -> ", name); 673216295Ssyrinx FindClassObjectClosure srch(name); 674216295Ssyrinx Universe::heap()->permanent_object_iterate(&srch); 675216295Ssyrinx } 676216295Ssyrinx} 677216295Ssyrinx 678216295Ssyrinx// Another interface that isn't ambiguous in dbx. 679216295Ssyrinx// Can we someday rename the other find to hsfind? 680216295Ssyrinxextern "C" void hsfind(intptr_t x) { 681216295Ssyrinx Command c("hsfind"); 682216295Ssyrinx os::print_location(tty, x, false); 683216295Ssyrinx} 684216295Ssyrinx 685216295Ssyrinx 686216295Ssyrinxextern "C" void hsfindref(intptr_t x) { 687216295Ssyrinx Command c("hsfindref"); 688216295Ssyrinx findref(x); 689216295Ssyrinx} 690216295Ssyrinx 691216295Ssyrinxextern "C" void find(intptr_t x) { 692216295Ssyrinx Command c("find"); 693216295Ssyrinx os::print_location(tty, x, false); 694311594Sngie} 695216295Ssyrinx 696216295Ssyrinx 697216295Ssyrinxextern "C" void findpc(intptr_t x) { 698216295Ssyrinx Command c("findpc"); 699216295Ssyrinx os::print_location(tty, x, true); 700216295Ssyrinx} 701216295Ssyrinx 702216295Ssyrinx 703216295Ssyrinx// int versions of all methods to avoid having to type type casts in the debugger 704216295Ssyrinx 705216295Ssyrinxvoid pp(intptr_t p) { pp((void*)p); } 706216295Ssyrinxvoid pp(oop p) { pp((void*)p); } 707216295Ssyrinx 708216295Ssyrinxvoid help() { 709216295Ssyrinx Command c("help"); 710216295Ssyrinx tty->print_cr("basic"); 711216295Ssyrinx tty->print_cr(" pp(void* p) - try to make sense of p"); 712216295Ssyrinx tty->print_cr(" pv(intptr_t p)- ((PrintableResourceObj*) p)->print()"); 713216295Ssyrinx tty->print_cr(" ps() - print current thread stack"); 714216295Ssyrinx tty->print_cr(" pss() - print all thread stacks"); 715216295Ssyrinx tty->print_cr(" pm(int pc) - print methodOop given compiled PC"); 716216295Ssyrinx tty->print_cr(" findm(intptr_t pc) - finds methodOop"); 717216295Ssyrinx tty->print_cr(" find(intptr_t x) - finds & prints nmethod/stub/bytecode/oop based on pointer into it"); 718216295Ssyrinx 719216295Ssyrinx tty->print_cr("misc."); 720216295Ssyrinx tty->print_cr(" flush() - flushes the log file"); 721216295Ssyrinx tty->print_cr(" events() - dump last 50 events"); 722216295Ssyrinx 723216295Ssyrinx 724216295Ssyrinx tty->print_cr("compiler debugging"); 725216295Ssyrinx tty->print_cr(" debug() - to set things up for compiler debugging"); 726216295Ssyrinx tty->print_cr(" ndebug() - undo debug"); 727216295Ssyrinx} 728216295Ssyrinx 729216295Ssyrinx#if 0 730216295Ssyrinx 731216295Ssyrinx// BobV's command parser for debugging on windows when nothing else works. 732216295Ssyrinx 733216295Ssyrinxenum CommandID { 734216295Ssyrinx CMDID_HELP, 735216295Ssyrinx CMDID_QUIT, 736216295Ssyrinx CMDID_HSFIND, 737216295Ssyrinx CMDID_PSS, 738216295Ssyrinx CMDID_PS, 739216295Ssyrinx CMDID_PSF, 740216295Ssyrinx CMDID_FINDM, 741216295Ssyrinx CMDID_FINDNM, 742216295Ssyrinx CMDID_PP, 743216295Ssyrinx CMDID_BPT, 744216295Ssyrinx CMDID_EXIT, 745216295Ssyrinx CMDID_VERIFY, 746216295Ssyrinx CMDID_THREADS, 747216295Ssyrinx CMDID_ILLEGAL = 99 748311594Sngie}; 749216295Ssyrinx 750216295Ssyrinxstruct CommandParser { 751216295Ssyrinx char *name; 752216295Ssyrinx CommandID code; 753216295Ssyrinx char *description; 754216295Ssyrinx}; 755216295Ssyrinx 756216295Ssyrinxstruct CommandParser CommandList[] = { 757216295Ssyrinx (char *)"help", CMDID_HELP, " Dump this list", 758216295Ssyrinx (char *)"quit", CMDID_QUIT, " Return from this routine", 759216295Ssyrinx (char *)"hsfind", CMDID_HSFIND, "Perform an hsfind on an address", 760216295Ssyrinx (char *)"ps", CMDID_PS, " Print Current Thread Stack Trace", 761216295Ssyrinx (char *)"pss", CMDID_PSS, " Print All Thread Stack Trace", 762216295Ssyrinx (char *)"psf", CMDID_PSF, " Print All Stack Frames", 763216295Ssyrinx (char *)"findm", CMDID_FINDM, " Find a methodOop from a PC", 764216295Ssyrinx (char *)"findnm", CMDID_FINDNM, "Find an nmethod from a PC", 765216295Ssyrinx (char *)"pp", CMDID_PP, " Find out something about a pointer", 766216295Ssyrinx (char *)"break", CMDID_BPT, " Execute a breakpoint", 767216295Ssyrinx (char *)"exitvm", CMDID_EXIT, "Exit the VM", 768216295Ssyrinx (char *)"verify", CMDID_VERIFY, "Perform a Heap Verify", 769216295Ssyrinx (char *)"thread", CMDID_THREADS, "Dump Info on all Threads", 770216295Ssyrinx (char *)0, CMDID_ILLEGAL 771216295Ssyrinx}; 772216295Ssyrinx 773216295Ssyrinx 774216295Ssyrinx// get_debug_command() 775216295Ssyrinx// 776216295Ssyrinx// Read a command from standard input. 777216295Ssyrinx// This is useful when you have a debugger 778216295Ssyrinx// which doesn't support calling into functions. 779216295Ssyrinx// 780216295Ssyrinxvoid get_debug_command() 781216295Ssyrinx{ 782216295Ssyrinx ssize_t count; 783216295Ssyrinx int i,j; 784216295Ssyrinx bool gotcommand; 785216295Ssyrinx intptr_t addr; 786216295Ssyrinx char buffer[256]; 787216295Ssyrinx nmethod *nm; 788216295Ssyrinx methodOop m; 789310901Sngie 790216295Ssyrinx tty->print_cr("You have entered the diagnostic command interpreter"); 791216295Ssyrinx tty->print("The supported commands are:\n"); 792216295Ssyrinx for ( i=0; ; i++ ) { 793216295Ssyrinx if ( CommandList[i].code == CMDID_ILLEGAL ) 794216295Ssyrinx break; 795216295Ssyrinx tty->print_cr(" %s \n", CommandList[i].name ); 796216295Ssyrinx } 797216295Ssyrinx 798216295Ssyrinx while ( 1 ) { 799216295Ssyrinx gotcommand = false; 800216295Ssyrinx tty->print("Please enter a command: "); 801216295Ssyrinx count = scanf("%s", buffer) ; 802216295Ssyrinx if ( count >=0 ) { 803216295Ssyrinx for ( i=0; ; i++ ) { 804216295Ssyrinx if ( CommandList[i].code == CMDID_ILLEGAL ) { 805216295Ssyrinx if (!gotcommand) tty->print("Invalid command, please try again\n"); 806216295Ssyrinx break; 807216295Ssyrinx } 808216295Ssyrinx if ( strcmp(buffer, CommandList[i].name) == 0 ) { 809216295Ssyrinx gotcommand = true; 810216295Ssyrinx switch ( CommandList[i].code ) { 811216295Ssyrinx case CMDID_PS: 812216295Ssyrinx ps(); 813216295Ssyrinx break; 814216295Ssyrinx case CMDID_PSS: 815216295Ssyrinx pss(); 816216295Ssyrinx break; 817216295Ssyrinx case CMDID_PSF: 818216295Ssyrinx psf(); 819216295Ssyrinx break; 820216295Ssyrinx case CMDID_FINDM: 821216295Ssyrinx tty->print("Please enter the hex addr to pass to findm: "); 822216295Ssyrinx scanf("%I64X", &addr); 823216295Ssyrinx m = (methodOop)findm(addr); 824216295Ssyrinx tty->print("findm(0x%I64X) returned 0x%I64X\n", addr, m); 825216295Ssyrinx break; 826216295Ssyrinx case CMDID_FINDNM: 827216295Ssyrinx tty->print("Please enter the hex addr to pass to findnm: "); 828216295Ssyrinx scanf("%I64X", &addr); 829216295Ssyrinx nm = (nmethod*)findnm(addr); 830216295Ssyrinx tty->print("findnm(0x%I64X) returned 0x%I64X\n", addr, nm); 831216295Ssyrinx break; 832216295Ssyrinx case CMDID_PP: 833311594Sngie tty->print("Please enter the hex addr to pass to pp: "); 834216295Ssyrinx scanf("%I64X", &addr); 835216295Ssyrinx pp((void*)addr); 836216295Ssyrinx break; 837216295Ssyrinx case CMDID_EXIT: 838216295Ssyrinx exit(0); 839216295Ssyrinx case CMDID_HELP: 840216295Ssyrinx tty->print("Here are the supported commands: "); 841216295Ssyrinx for ( j=0; ; j++ ) { 842311594Sngie if ( CommandList[j].code == CMDID_ILLEGAL ) 843216295Ssyrinx break; 844216295Ssyrinx tty->print_cr(" %s -- %s\n", CommandList[j].name, 845216295Ssyrinx CommandList[j].description ); 846216295Ssyrinx } 847216295Ssyrinx break; 848216295Ssyrinx case CMDID_QUIT: 849216295Ssyrinx return; 850216295Ssyrinx break; 851216295Ssyrinx case CMDID_BPT: 852216295Ssyrinx BREAKPOINT; 853311465Sngie break; 854311465Sngie case CMDID_VERIFY: 855216295Ssyrinx verify();; 856216295Ssyrinx break; 857216295Ssyrinx case CMDID_THREADS: 858216295Ssyrinx threads();; 859216295Ssyrinx break; 860216295Ssyrinx case CMDID_HSFIND: 861216295Ssyrinx tty->print("Please enter the hex addr to pass to hsfind: "); 862216295Ssyrinx scanf("%I64X", &addr); 863216295Ssyrinx tty->print("Calling hsfind(0x%I64X)\n", addr); 864216295Ssyrinx hsfind(addr); 865216295Ssyrinx break; 866216295Ssyrinx default: 867216295Ssyrinx case CMDID_ILLEGAL: 868216295Ssyrinx break; 869216295Ssyrinx } 870216295Ssyrinx } 871216295Ssyrinx } 872216295Ssyrinx } 873216295Ssyrinx } 874216295Ssyrinx} 875216295Ssyrinx#endif 876216295Ssyrinx 877216295Ssyrinx#endif // PRODUCT 878216295Ssyrinx