debug.cpp revision 227
/*
* Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*
*/
# include "incls/_precompiled.incl"
# include "incls/_debug.cpp.incl"
#ifndef ASSERT
# ifdef _DEBUG
// NOTE: don't turn the lines below into a comment -- if you're getting
// a compile error here, change the settings to define ASSERT
# endif // _DEBUG
#endif // ASSERT
#ifdef _DEBUG
# ifndef ASSERT
# endif // ASSERT
#endif // _DEBUG
#ifdef PRODUCT
# endif
#endif // PRODUCT
// In case error happens before init or during shutdown
if (BreakAtWarning) BREAKPOINT;
}
#ifndef PRODUCT
static const char* last_file_name = NULL;
static int last_line_no = -1;
// Don't rely on anything that is initialized by Threads::create_vm(). For
// example, don't use tty.
// The following 1-element cache requires that passed-in
// file names are always only constant literals.
// scan the SuppressErrorAt option
const char* cp = SuppressErrorAt;
for (;;) {
const char* sfile;
int sfile_len;
int sline;
bool noisy;
if ((*cp) == '\0') break;
sline = 0;
sline *= 10;
cp++;
}
// "file:line!" means the assert suppression is not silent
// match the line
if (sline != 0) {
}
// match the file
if (sfile_len > 0) {
const char* foundp;
bool match = false;
while (!match
match = true;
for (int i = 1; i < sfile_len; i++) {
match = false;
break;
}
}
}
if (!match) continue;
}
// got a match!
if (noisy) {
char buf[16];
} else {
// update 1-element cache for fast silent matches
}
return true;
}
if (!is_error_reported()) {
// print a friendly hint:
char buf[16];
}
return false;
}
#else
// Place-holder for non-existent suppression check:
#endif //PRODUCT
}
}
char buffer[256];
}
// Used by report_vm_out_of_memory to detect recursion.
static jint _exiting_out_of_mem = 0;
// Just passing the flow to VMError to handle error
void report_vm_out_of_memory(const char* file_name, int line_no, size_t size, const char* message) {
// We try to gather additional information for the first out of memory
// error only; gathering additional data might cause an allocation and a
// recursive out_of_memory condition.
// If we succeed in changing the value, we're the first one in.
if (first_time_here) {
}
// Dump core and abort
vm_abort(true);
}
void report_vm_out_of_memory_vararg(const char* file_name, int line_no, size_t size, const char* format, ...) {
char buffer[256];
}
}
}
}
#ifndef PRODUCT
#endif // PRODUCT
}
void report_java_out_of_memory(const char* message) {
static jint out_of_memory_reported = 0;
// A number of threads may attempt to report OutOfMemoryError at around the
// same time. To avoid dumping the heap or executing the data collection
// commands multiple times we just do it once when the first threads reports
// the error.
// create heap dump before OnOutOfMemoryError commands are executed
if (HeapDumpOnOutOfMemoryError) {
HeapDumper::dump_heap();
}
if (OnOutOfMemoryError && OnOutOfMemoryError[0]) {
}
}
}
extern "C" void ps();
static bool error_reported = false;
// call this when the VM is dying--it might loosen some asserts
void set_error_reported() {
error_reported = true;
}
bool is_error_reported() {
return error_reported;
}
// ------ helper functions for debugging go here ------------
#ifndef PRODUCT
// All debug entries should be wrapped with a stack allocated
// Command object. It makes sure a resource mark is set and
// flushes the logfile to prevent file sharing problems.
private:
bool debug_save;
public:
static int level;
Debugging = true;
if (level++ > 0) return;
}
};
Command c("blob");
}
Command c("dump_vtable");
}
// Actually we look through all CodeBlobs (the nm name has been kept for backwards compatability)
Command c("nm");
} else {
}
}
Command c("disnm");
}
char buffer[256];
if (cb->is_nmethod()) {
nm->print_nmethod(true);
}
}
extern "C" void universe() {
Command c("universe");
}
extern "C" void verify() {
// try to run a verify on the entire system
// note: this may not be safe if we're not at a safepoint; for debugging,
// this manipulates the safepoint settings to avoid assertion failures
Command c("universe verify");
if (!safe) {
}
// Ensure Eden top is correct before verification
}
extern "C" void pp(void* p) {
Command c("pp");
} else {
}
}
// pv: print vm-printable object
Command c("ps");
// Prints the stack of the current Java thread
p->print();
if (p->has_last_Java_frame()) {
// If the last_Java_fp is set we are in C land and
// can call the standard stack_trace function.
p->trace_stack();
} else {
RegisterMap reg_map(p);
pd_ps(f);
}
}
{
Command c("psf");
p->print();
if (p->has_last_Java_frame()) {
p->trace_frames();
}
}
}
extern "C" void threads() {
Command c("threads");
}
extern "C" void psd() {
Command c("psd");
}
extern "C" void safepoints() {
Command c("safepoints");
}
Command c("pss");
}
Command c("debug");
WizardMode = true;
PrintVMMessages = PrintCompilation = true;
PrintInlining = PrintAssembly = true;
}
Command c("ndebug");
PrintCompilation = false;
PrintInlining = PrintAssembly = false;
}
extern "C" void flush() {
Command c("flush");
}
extern "C" void events() {
Command c("events");
}
extern "C" void nevents(int n) {
Command c("events");
}
// Given a heap address that was valid before the most recent GC, if
// the oop that used to contain it is still live, prints the new
// location of the oop and the address. Useful for tracking down
// certain kinds of naked oop and oop map bugs.
// Print New Location of old heap address
Command c("pnl");
#ifndef VALIDATE_MARK_SWEEP
tty->print_cr("Requires build with VALIDATE_MARK_SWEEP defined (debug build) and RecordMarkSweepCompaction enabled");
#else
#endif
}
Command c("findm");
}
Command c("findnm");
}
return x;
} else if (x > y) {
} else {
}
}
if (b != NULL) {
if (b->is_buffer_blob()) {
// the interpreter is generated into a buffer blob
if (i != NULL) {
i->print();
return;
}
return;
}
//
if (AdapterHandlerLibrary::contains(b)) {
}
// the stubroutines are generated into a buffer blob
if (d != NULL) {
d->print();
return;
}
return;
}
// the InlineCacheBuffer is using stubs generated into a buffer blob
return;
}
if (v != NULL) {
v->print();
return;
}
}
if (print_pc && b->is_nmethod()) {
return;
}
if ( b->is_nmethod()) {
if (b->is_zombie()) {
} else if (b->is_not_entrant()) {
}
}
b->print();
return;
}
bool print = false;
// If we couldn't find it it just may mean that heap wasn't parseable
// See if we were just given an oop directly
print = true;
print = true;
}
if (print) {
mh->print_codes();
}
}
return;
}
}
return;
}
return;
}
return;
}
// Check for priviledge stack
tty->print_cr(INTPTR_FORMAT "is pointing into the priviledge stack for thread: " INTPTR_FORMAT, addr, thread);
return;
}
// If the addr is a java thread print information about that.
return;
}
}
// Try an OS specific find
return;
}
if (print_pc) {
return;
}
}
class LookForRefInGenClosure : public OopsInGenClosure {
public:
}
}
};
class LookForRefInObjectClosure : public ObjectClosure {
private:
public:
}
};
//FlatProfiler::oops_do(&lookFor);
}
class FindClassObjectClosure: public ObjectClosure {
private:
const char* _target;
public:
const char* ext = k->external_name();
}
}
}
}
};
//
Command c("findclass");
}
}
// Another interface that isn't ambiguous in dbx.
// Can we someday rename the other find to hsfind?
Command c("hsfind");
find(x, false);
}
Command c("hsfindref");
findref(x);
}
Command c("find");
find(x, false);
}
Command c("findpc");
find(x, true);
}
// int versions of all methods to avoid having to type type casts in the debugger
void help() {
Command c("help");
tty->print_cr(" find(intptr_t x) - finds & prints nmethod/stub/bytecode/oop based on pointer into it");
}
#if 0
// BobV's command parser for debugging on windows when nothing else works.
enum CommandID {
CMDID_ILLEGAL = 99
};
struct CommandParser {
char *name;
char *description;
};
struct CommandParser CommandList[] = {
(char *)0, CMDID_ILLEGAL
};
// get_debug_command()
//
// Read a command from standard input.
// This is useful when you have a debugger
// which doesn't support calling into functions.
//
void get_debug_command()
{
int i,j;
bool gotcommand;
char buffer[256];
methodOop m;
for ( i=0; ; i++ ) {
break;
}
while ( 1 ) {
gotcommand = false;
if ( count >=0 ) {
for ( i=0; ; i++ ) {
break;
}
gotcommand = true;
switch ( CommandList[i].code ) {
case CMDID_PS:
ps();
break;
case CMDID_PSS:
pss();
break;
case CMDID_PSF:
psf();
break;
case CMDID_FINDM:
break;
case CMDID_FINDNM:
break;
case CMDID_PP:
break;
case CMDID_EXIT:
exit(0);
case CMDID_HELP:
for ( j=0; ; j++ ) {
break;
CommandList[j].description );
}
break;
case CMDID_QUIT:
return;
break;
case CMDID_BPT:
break;
case CMDID_VERIFY:
verify();;
break;
case CMDID_THREADS:
threads();;
break;
case CMDID_HSFIND:
break;
default:
case CMDID_ILLEGAL:
break;
}
}
}
}
}
}
#endif
#endif // PRODUCT