fe008ae27a
Reviewed-by: darcy, weijun
330 lines
13 KiB
C
330 lines
13 KiB
C
/*
|
|
* Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved.
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
* This code is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License version 2 only, as
|
|
* published by the Free Software Foundation. Oracle designates this
|
|
* particular file as subject to the "Classpath" exception as provided
|
|
* by Oracle in the LICENSE file that accompanied this code.
|
|
*
|
|
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
* or visit www.oracle.com if you need additional information or have any
|
|
* questions.
|
|
*/
|
|
|
|
/* Error message and general message handling functions. */
|
|
|
|
/* NOTE: We assume that most strings passed around this library are
|
|
* UTF-8 (modified or standard) and not platform encoding.
|
|
* Before sending any strings to the "system" (e.g. OS system
|
|
* calls, or system input/output functions like fprintf) we need
|
|
* to make sure that the strings are transformed from UTF-8 to
|
|
* the platform encoding accepted by the system.
|
|
* UTF-8 and most encodings have simple ASCII or ISO-Latin
|
|
* characters as a subset, so in most cases the strings really
|
|
* don't need to be converted, but we don't know that easily.
|
|
* Parts of messages can be non-ASCII in some cases, so they may
|
|
* include classnames, methodnames, signatures, or other pieces
|
|
* that could contain non-ASCII characters, either from JNI or
|
|
* JVMTI (which both return modified UTF-8 strings).
|
|
* (It's possible that the platform encoding IS UTF-8, but we
|
|
* assume not, just to be safe).
|
|
*
|
|
*/
|
|
|
|
#include <stdarg.h>
|
|
#include <errno.h>
|
|
|
|
#include "util.h"
|
|
#include "proc_md.h"
|
|
|
|
/* Maximim length of a message */
|
|
#define MAX_MESSAGE_LEN MAXPATHLEN*2+512
|
|
|
|
/* Print message in platform encoding (assume all input is UTF-8 safe)
|
|
* NOTE: This function is at the lowest level of the call tree.
|
|
* Do not use the ERROR* macros here.
|
|
*/
|
|
static void
|
|
vprint_message(FILE *fp, const char *prefix, const char *suffix,
|
|
const char *format, va_list ap)
|
|
{
|
|
jbyte utf8buf[MAX_MESSAGE_LEN+1];
|
|
int len;
|
|
char pbuf[MAX_MESSAGE_LEN+1];
|
|
|
|
/* Fill buffer with single UTF-8 string */
|
|
(void)vsnprintf((char*)utf8buf, MAX_MESSAGE_LEN, format, ap);
|
|
utf8buf[MAX_MESSAGE_LEN] = 0;
|
|
len = (int)strlen((char*)utf8buf);
|
|
|
|
/* Convert to platform encoding (ignore errors, dangerous area) */
|
|
(void)(gdata->npt->utf8ToPlatform)(gdata->npt->utf,
|
|
utf8buf, len, pbuf, MAX_MESSAGE_LEN);
|
|
(void)fprintf(fp, "%s%s%s", prefix, pbuf, suffix);
|
|
}
|
|
|
|
/* Print message in platform encoding (assume all input is UTF-8 safe)
|
|
* NOTE: This function is at the lowest level of the call tree.
|
|
* Do not use the ERROR* macros here.
|
|
*/
|
|
void
|
|
print_message(FILE *fp, const char *prefix, const char *suffix,
|
|
const char *format, ...)
|
|
{
|
|
va_list ap;
|
|
|
|
va_start(ap, format);
|
|
vprint_message(fp, prefix, suffix, format, ap);
|
|
va_end(ap);
|
|
}
|
|
|
|
/* Generate error message */
|
|
void
|
|
error_message(const char *format, ...)
|
|
{
|
|
va_list ap;
|
|
|
|
va_start(ap, format);
|
|
vprint_message(stderr, "ERROR: ", "\n", format, ap);
|
|
va_end(ap);
|
|
if ( gdata->doerrorexit ) {
|
|
EXIT_ERROR(AGENT_ERROR_INTERNAL,"Requested errorexit=y exit()");
|
|
}
|
|
}
|
|
|
|
/* Print plain message to stdout. */
|
|
void
|
|
tty_message(const char *format, ...)
|
|
{
|
|
va_list ap;
|
|
|
|
va_start(ap, format);
|
|
vprint_message(stdout, "", "\n", format, ap);
|
|
va_end(ap);
|
|
(void)fflush(stdout);
|
|
}
|
|
|
|
/* Print assertion error message to stderr. */
|
|
void
|
|
jdiAssertionFailed(char *fileName, int lineNumber, char *msg)
|
|
{
|
|
LOG_MISC(("ASSERT FAILED: %s : %d - %s\n", fileName, lineNumber, msg));
|
|
print_message(stderr, "ASSERT FAILED: ", "\n",
|
|
"%s : %d - %s", fileName, lineNumber, msg);
|
|
if (gdata && gdata->assertFatal) {
|
|
EXIT_ERROR(AGENT_ERROR_INTERNAL,"Assertion Failed");
|
|
}
|
|
}
|
|
|
|
/* Macro for case on switch, returns string for name. */
|
|
#define CASE_RETURN_TEXT(name) case name: return #name;
|
|
|
|
/* Mapping of JVMTI errors to their name */
|
|
const char *
|
|
jvmtiErrorText(jvmtiError error)
|
|
{
|
|
switch (error) {
|
|
CASE_RETURN_TEXT(JVMTI_ERROR_NONE)
|
|
CASE_RETURN_TEXT(JVMTI_ERROR_INVALID_THREAD)
|
|
CASE_RETURN_TEXT(JVMTI_ERROR_INVALID_THREAD_GROUP)
|
|
CASE_RETURN_TEXT(JVMTI_ERROR_INVALID_PRIORITY)
|
|
CASE_RETURN_TEXT(JVMTI_ERROR_THREAD_NOT_SUSPENDED)
|
|
CASE_RETURN_TEXT(JVMTI_ERROR_THREAD_SUSPENDED)
|
|
CASE_RETURN_TEXT(JVMTI_ERROR_THREAD_NOT_ALIVE)
|
|
CASE_RETURN_TEXT(JVMTI_ERROR_INVALID_OBJECT)
|
|
CASE_RETURN_TEXT(JVMTI_ERROR_INVALID_CLASS)
|
|
CASE_RETURN_TEXT(JVMTI_ERROR_CLASS_NOT_PREPARED)
|
|
CASE_RETURN_TEXT(JVMTI_ERROR_INVALID_METHODID)
|
|
CASE_RETURN_TEXT(JVMTI_ERROR_INVALID_LOCATION)
|
|
CASE_RETURN_TEXT(JVMTI_ERROR_INVALID_FIELDID)
|
|
CASE_RETURN_TEXT(JVMTI_ERROR_NO_MORE_FRAMES)
|
|
CASE_RETURN_TEXT(JVMTI_ERROR_OPAQUE_FRAME)
|
|
CASE_RETURN_TEXT(JVMTI_ERROR_TYPE_MISMATCH)
|
|
CASE_RETURN_TEXT(JVMTI_ERROR_INVALID_SLOT)
|
|
CASE_RETURN_TEXT(JVMTI_ERROR_DUPLICATE)
|
|
CASE_RETURN_TEXT(JVMTI_ERROR_NOT_FOUND)
|
|
CASE_RETURN_TEXT(JVMTI_ERROR_INVALID_MONITOR)
|
|
CASE_RETURN_TEXT(JVMTI_ERROR_NOT_MONITOR_OWNER)
|
|
CASE_RETURN_TEXT(JVMTI_ERROR_INTERRUPT)
|
|
CASE_RETURN_TEXT(JVMTI_ERROR_INVALID_CLASS_FORMAT)
|
|
CASE_RETURN_TEXT(JVMTI_ERROR_CIRCULAR_CLASS_DEFINITION)
|
|
CASE_RETURN_TEXT(JVMTI_ERROR_FAILS_VERIFICATION)
|
|
CASE_RETURN_TEXT(JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_ADDED)
|
|
CASE_RETURN_TEXT(JVMTI_ERROR_UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED)
|
|
CASE_RETURN_TEXT(JVMTI_ERROR_INVALID_TYPESTATE)
|
|
CASE_RETURN_TEXT(JVMTI_ERROR_UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED)
|
|
CASE_RETURN_TEXT(JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_DELETED)
|
|
CASE_RETURN_TEXT(JVMTI_ERROR_UNSUPPORTED_VERSION)
|
|
CASE_RETURN_TEXT(JVMTI_ERROR_NAMES_DONT_MATCH)
|
|
CASE_RETURN_TEXT(JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_MODIFIERS_CHANGED)
|
|
CASE_RETURN_TEXT(JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_MODIFIERS_CHANGED)
|
|
CASE_RETURN_TEXT(JVMTI_ERROR_NOT_AVAILABLE)
|
|
CASE_RETURN_TEXT(JVMTI_ERROR_MUST_POSSESS_CAPABILITY)
|
|
CASE_RETURN_TEXT(JVMTI_ERROR_NULL_POINTER)
|
|
CASE_RETURN_TEXT(JVMTI_ERROR_ABSENT_INFORMATION)
|
|
CASE_RETURN_TEXT(JVMTI_ERROR_INVALID_EVENT_TYPE)
|
|
CASE_RETURN_TEXT(JVMTI_ERROR_ILLEGAL_ARGUMENT)
|
|
CASE_RETURN_TEXT(JVMTI_ERROR_OUT_OF_MEMORY)
|
|
CASE_RETURN_TEXT(JVMTI_ERROR_ACCESS_DENIED)
|
|
CASE_RETURN_TEXT(JVMTI_ERROR_WRONG_PHASE)
|
|
CASE_RETURN_TEXT(JVMTI_ERROR_INTERNAL)
|
|
CASE_RETURN_TEXT(JVMTI_ERROR_UNATTACHED_THREAD)
|
|
CASE_RETURN_TEXT(JVMTI_ERROR_INVALID_ENVIRONMENT)
|
|
|
|
CASE_RETURN_TEXT(AGENT_ERROR_INTERNAL)
|
|
CASE_RETURN_TEXT(AGENT_ERROR_VM_DEAD)
|
|
CASE_RETURN_TEXT(AGENT_ERROR_NO_JNI_ENV)
|
|
CASE_RETURN_TEXT(AGENT_ERROR_JNI_EXCEPTION)
|
|
CASE_RETURN_TEXT(AGENT_ERROR_JVMTI_INTERNAL)
|
|
CASE_RETURN_TEXT(AGENT_ERROR_JDWP_INTERNAL)
|
|
CASE_RETURN_TEXT(AGENT_ERROR_NOT_CURRENT_FRAME)
|
|
CASE_RETURN_TEXT(AGENT_ERROR_OUT_OF_MEMORY)
|
|
CASE_RETURN_TEXT(AGENT_ERROR_INVALID_TAG)
|
|
CASE_RETURN_TEXT(AGENT_ERROR_ALREADY_INVOKING)
|
|
CASE_RETURN_TEXT(AGENT_ERROR_INVALID_INDEX)
|
|
CASE_RETURN_TEXT(AGENT_ERROR_INVALID_LENGTH)
|
|
CASE_RETURN_TEXT(AGENT_ERROR_INVALID_STRING)
|
|
CASE_RETURN_TEXT(AGENT_ERROR_INVALID_CLASS_LOADER)
|
|
CASE_RETURN_TEXT(AGENT_ERROR_INVALID_ARRAY)
|
|
CASE_RETURN_TEXT(AGENT_ERROR_TRANSPORT_LOAD)
|
|
CASE_RETURN_TEXT(AGENT_ERROR_TRANSPORT_INIT)
|
|
CASE_RETURN_TEXT(AGENT_ERROR_NATIVE_METHOD)
|
|
CASE_RETURN_TEXT(AGENT_ERROR_INVALID_COUNT)
|
|
CASE_RETURN_TEXT(AGENT_ERROR_INVALID_FRAMEID)
|
|
CASE_RETURN_TEXT(AGENT_ERROR_NULL_POINTER)
|
|
CASE_RETURN_TEXT(AGENT_ERROR_ILLEGAL_ARGUMENT)
|
|
CASE_RETURN_TEXT(AGENT_ERROR_INVALID_THREAD)
|
|
CASE_RETURN_TEXT(AGENT_ERROR_INVALID_EVENT_TYPE)
|
|
CASE_RETURN_TEXT(AGENT_ERROR_INVALID_OBJECT)
|
|
CASE_RETURN_TEXT(AGENT_ERROR_NO_MORE_FRAMES)
|
|
|
|
default: return "ERROR_unknown";
|
|
}
|
|
}
|
|
|
|
const char *
|
|
eventText(int i)
|
|
{
|
|
switch ( i ) {
|
|
CASE_RETURN_TEXT(EI_SINGLE_STEP)
|
|
CASE_RETURN_TEXT(EI_BREAKPOINT)
|
|
CASE_RETURN_TEXT(EI_FRAME_POP)
|
|
CASE_RETURN_TEXT(EI_EXCEPTION)
|
|
CASE_RETURN_TEXT(EI_THREAD_START)
|
|
CASE_RETURN_TEXT(EI_THREAD_END)
|
|
CASE_RETURN_TEXT(EI_CLASS_PREPARE)
|
|
CASE_RETURN_TEXT(EI_CLASS_LOAD)
|
|
CASE_RETURN_TEXT(EI_FIELD_ACCESS)
|
|
CASE_RETURN_TEXT(EI_FIELD_MODIFICATION)
|
|
CASE_RETURN_TEXT(EI_EXCEPTION_CATCH)
|
|
CASE_RETURN_TEXT(EI_METHOD_ENTRY)
|
|
CASE_RETURN_TEXT(EI_METHOD_EXIT)
|
|
CASE_RETURN_TEXT(EI_VM_INIT)
|
|
CASE_RETURN_TEXT(EI_VM_DEATH)
|
|
CASE_RETURN_TEXT(EI_GC_FINISH)
|
|
default: return "EVENT_unknown";
|
|
}
|
|
}
|
|
|
|
/* Macro for case on switch, returns string for name. */
|
|
#define CASE_RETURN_JDWP_ERROR_TEXT(name) case JDWP_ERROR(name): return #name;
|
|
|
|
const char *
|
|
jdwpErrorText(jdwpError serror)
|
|
{
|
|
switch ( serror ) {
|
|
CASE_RETURN_JDWP_ERROR_TEXT(NONE)
|
|
CASE_RETURN_JDWP_ERROR_TEXT(INVALID_THREAD)
|
|
CASE_RETURN_JDWP_ERROR_TEXT(INVALID_THREAD_GROUP)
|
|
CASE_RETURN_JDWP_ERROR_TEXT(INVALID_PRIORITY)
|
|
CASE_RETURN_JDWP_ERROR_TEXT(THREAD_NOT_SUSPENDED)
|
|
CASE_RETURN_JDWP_ERROR_TEXT(THREAD_SUSPENDED)
|
|
CASE_RETURN_JDWP_ERROR_TEXT(INVALID_OBJECT)
|
|
CASE_RETURN_JDWP_ERROR_TEXT(INVALID_CLASS)
|
|
CASE_RETURN_JDWP_ERROR_TEXT(CLASS_NOT_PREPARED)
|
|
CASE_RETURN_JDWP_ERROR_TEXT(INVALID_METHODID)
|
|
CASE_RETURN_JDWP_ERROR_TEXT(INVALID_LOCATION)
|
|
CASE_RETURN_JDWP_ERROR_TEXT(INVALID_FIELDID)
|
|
CASE_RETURN_JDWP_ERROR_TEXT(INVALID_FRAMEID)
|
|
CASE_RETURN_JDWP_ERROR_TEXT(NO_MORE_FRAMES)
|
|
CASE_RETURN_JDWP_ERROR_TEXT(OPAQUE_FRAME)
|
|
CASE_RETURN_JDWP_ERROR_TEXT(NOT_CURRENT_FRAME)
|
|
CASE_RETURN_JDWP_ERROR_TEXT(TYPE_MISMATCH)
|
|
CASE_RETURN_JDWP_ERROR_TEXT(INVALID_SLOT)
|
|
CASE_RETURN_JDWP_ERROR_TEXT(DUPLICATE)
|
|
CASE_RETURN_JDWP_ERROR_TEXT(NOT_FOUND)
|
|
CASE_RETURN_JDWP_ERROR_TEXT(INVALID_MONITOR)
|
|
CASE_RETURN_JDWP_ERROR_TEXT(NOT_MONITOR_OWNER)
|
|
CASE_RETURN_JDWP_ERROR_TEXT(INTERRUPT)
|
|
CASE_RETURN_JDWP_ERROR_TEXT(INVALID_CLASS_FORMAT)
|
|
CASE_RETURN_JDWP_ERROR_TEXT(CIRCULAR_CLASS_DEFINITION)
|
|
CASE_RETURN_JDWP_ERROR_TEXT(FAILS_VERIFICATION)
|
|
CASE_RETURN_JDWP_ERROR_TEXT(ADD_METHOD_NOT_IMPLEMENTED)
|
|
CASE_RETURN_JDWP_ERROR_TEXT(SCHEMA_CHANGE_NOT_IMPLEMENTED)
|
|
CASE_RETURN_JDWP_ERROR_TEXT(INVALID_TYPESTATE)
|
|
CASE_RETURN_JDWP_ERROR_TEXT(HIERARCHY_CHANGE_NOT_IMPLEMENTED)
|
|
CASE_RETURN_JDWP_ERROR_TEXT(DELETE_METHOD_NOT_IMPLEMENTED)
|
|
CASE_RETURN_JDWP_ERROR_TEXT(UNSUPPORTED_VERSION)
|
|
CASE_RETURN_JDWP_ERROR_TEXT(NAMES_DONT_MATCH)
|
|
CASE_RETURN_JDWP_ERROR_TEXT(CLASS_MODIFIERS_CHANGE_NOT_IMPLEMENTED)
|
|
CASE_RETURN_JDWP_ERROR_TEXT(METHOD_MODIFIERS_CHANGE_NOT_IMPLEMENTED)
|
|
CASE_RETURN_JDWP_ERROR_TEXT(NOT_IMPLEMENTED)
|
|
CASE_RETURN_JDWP_ERROR_TEXT(NULL_POINTER)
|
|
CASE_RETURN_JDWP_ERROR_TEXT(ABSENT_INFORMATION)
|
|
CASE_RETURN_JDWP_ERROR_TEXT(INVALID_EVENT_TYPE)
|
|
CASE_RETURN_JDWP_ERROR_TEXT(ILLEGAL_ARGUMENT)
|
|
CASE_RETURN_JDWP_ERROR_TEXT(OUT_OF_MEMORY)
|
|
CASE_RETURN_JDWP_ERROR_TEXT(ACCESS_DENIED)
|
|
CASE_RETURN_JDWP_ERROR_TEXT(VM_DEAD)
|
|
CASE_RETURN_JDWP_ERROR_TEXT(INTERNAL)
|
|
CASE_RETURN_JDWP_ERROR_TEXT(UNATTACHED_THREAD)
|
|
CASE_RETURN_JDWP_ERROR_TEXT(INVALID_TAG)
|
|
CASE_RETURN_JDWP_ERROR_TEXT(ALREADY_INVOKING)
|
|
CASE_RETURN_JDWP_ERROR_TEXT(INVALID_INDEX)
|
|
CASE_RETURN_JDWP_ERROR_TEXT(INVALID_LENGTH)
|
|
CASE_RETURN_JDWP_ERROR_TEXT(INVALID_STRING)
|
|
CASE_RETURN_JDWP_ERROR_TEXT(INVALID_CLASS_LOADER)
|
|
CASE_RETURN_JDWP_ERROR_TEXT(INVALID_ARRAY)
|
|
CASE_RETURN_JDWP_ERROR_TEXT(TRANSPORT_LOAD)
|
|
CASE_RETURN_JDWP_ERROR_TEXT(TRANSPORT_INIT)
|
|
CASE_RETURN_JDWP_ERROR_TEXT(NATIVE_METHOD)
|
|
CASE_RETURN_JDWP_ERROR_TEXT(INVALID_COUNT)
|
|
default: return "JDWP_ERROR_unknown";
|
|
}
|
|
}
|
|
|
|
static int p = 1;
|
|
|
|
void
|
|
do_pause(void)
|
|
{
|
|
THREAD_T tid = GET_THREAD_ID();
|
|
PID_T pid = GETPID();
|
|
int timeleft = 600; /* 10 minutes max */
|
|
int interval = 10; /* 10 second message check */
|
|
|
|
/*LINTED*/
|
|
tty_message("DEBUGGING: JDWP pause for PID %d, THREAD %d (0x%x)",
|
|
/*LINTED*/
|
|
(int)(intptr_t)pid, (int)(intptr_t)tid, (int)(intptr_t)tid);
|
|
while ( p && timeleft > 0 ) {
|
|
(void)sleep(interval); /* 'assign p = 0;' to get out of loop */
|
|
timeleft -= interval;
|
|
}
|
|
if ( timeleft <= 0 ) {
|
|
tty_message("DEBUGGING: JDWP pause got tired of waiting and gave up.");
|
|
}
|
|
}
|