Merge
This commit is contained in:
commit
2a7612efba
hotspot
agent/src
src/os
@ -22,6 +22,9 @@
|
||||
*
|
||||
*/
|
||||
|
||||
// Disable CRT security warning against strcpy/strcat
|
||||
#pragma warning(disable: 4996)
|
||||
|
||||
// this is source code windbg based SA debugger agent to debug
|
||||
// Dr. Watson dump files and process snapshots.
|
||||
|
||||
|
@ -33,6 +33,8 @@
|
||||
*/
|
||||
|
||||
#ifdef _WINDOWS
|
||||
// Disable CRT security warning against _snprintf
|
||||
#pragma warning (disable : 4996)
|
||||
|
||||
#define snprintf _snprintf
|
||||
#define vsnprintf _vsnprintf
|
||||
@ -90,12 +92,8 @@ static int getLastErrorString(char *buf, size_t len)
|
||||
if (errno != 0)
|
||||
{
|
||||
/* C runtime error that has no corresponding DOS error code */
|
||||
const char *s = strerror(errno);
|
||||
size_t n = strlen(s);
|
||||
if (n >= len) n = len - 1;
|
||||
strncpy(buf, s, n);
|
||||
buf[n] = '\0';
|
||||
return (int)n;
|
||||
strerror_s(buf, len, errno);
|
||||
return strlen(buf);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -111,16 +109,30 @@ JNIEXPORT jlong JNICALL Java_sun_jvm_hotspot_asm_Disassembler_load_1library(JNIE
|
||||
jstring jrepath_s,
|
||||
jstring libname_s) {
|
||||
uintptr_t func = 0;
|
||||
const char* error_message = NULL;
|
||||
jboolean isCopy;
|
||||
|
||||
const char * jrepath = (*env)->GetStringUTFChars(env, jrepath_s, &isCopy); // like $JAVA_HOME/jre/lib/sparc/
|
||||
const char * libname = (*env)->GetStringUTFChars(env, libname_s, &isCopy);
|
||||
const char *error_message = NULL;
|
||||
const char *jrepath = NULL;
|
||||
const char *libname = NULL;
|
||||
char buffer[128];
|
||||
|
||||
#ifdef _WINDOWS
|
||||
HINSTANCE hsdis_handle = (HINSTANCE) NULL;
|
||||
#else
|
||||
void* hsdis_handle = NULL;
|
||||
#endif
|
||||
|
||||
jrepath = (*env)->GetStringUTFChars(env, jrepath_s, NULL); // like $JAVA_HOME/jre/lib/sparc/
|
||||
if (jrepath == NULL || (*env)->ExceptionOccurred(env)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
libname = (*env)->GetStringUTFChars(env, libname_s, NULL);
|
||||
if (libname == NULL || (*env)->ExceptionOccurred(env)) {
|
||||
(*env)->ReleaseStringUTFChars(env, jrepath_s, jrepath);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Load the hsdis library */
|
||||
#ifdef _WINDOWS
|
||||
HINSTANCE hsdis_handle;
|
||||
hsdis_handle = LoadLibrary(libname);
|
||||
if (hsdis_handle == NULL) {
|
||||
snprintf(buffer, sizeof(buffer), "%s%s", jrepath, libname);
|
||||
@ -134,7 +146,6 @@ JNIEXPORT jlong JNICALL Java_sun_jvm_hotspot_asm_Disassembler_load_1library(JNIE
|
||||
error_message = buffer;
|
||||
}
|
||||
#else
|
||||
void* hsdis_handle;
|
||||
hsdis_handle = dlopen(libname, RTLD_LAZY | RTLD_GLOBAL);
|
||||
if (hsdis_handle == NULL) {
|
||||
snprintf(buffer, sizeof(buffer), "%s%s", jrepath, libname);
|
||||
@ -156,6 +167,11 @@ JNIEXPORT jlong JNICALL Java_sun_jvm_hotspot_asm_Disassembler_load_1library(JNIE
|
||||
* platform dependent error message.
|
||||
*/
|
||||
jclass eclass = (*env)->FindClass(env, "sun/jvm/hotspot/debugger/DebuggerException");
|
||||
if ((*env)->ExceptionOccurred(env)) {
|
||||
/* Can't throw exception, probably OOM, so silently return 0 */
|
||||
return (jlong) 0;
|
||||
}
|
||||
|
||||
(*env)->ThrowNew(env, eclass, error_message);
|
||||
}
|
||||
return (jlong)func;
|
||||
@ -184,16 +200,22 @@ typedef struct {
|
||||
|
||||
/* event callback binding to Disassembler.handleEvent */
|
||||
static void* event_to_env(void* env_pv, const char* event, void* arg) {
|
||||
jlong result = 0;
|
||||
decode_env* denv = (decode_env*)env_pv;
|
||||
JNIEnv* env = denv->env;
|
||||
jstring event_string = (*env)->NewStringUTF(env, event);
|
||||
jlong result = (*env)->CallLongMethod(env, denv->dis, denv->handle_event, denv->visitor,
|
||||
event_string, (jlong) (uintptr_t)arg);
|
||||
if ((*env)->ExceptionOccurred(env) != NULL) {
|
||||
if ((*env)->ExceptionOccurred(env)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
result = (*env)->CallLongMethod(env, denv->dis, denv->handle_event, denv->visitor,
|
||||
event_string, (jlong) (uintptr_t)arg);
|
||||
if ((*env)->ExceptionOccurred(env)) {
|
||||
/* ignore exceptions for now */
|
||||
(*env)->ExceptionClear(env);
|
||||
result = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (void*)(uintptr_t)result;
|
||||
}
|
||||
|
||||
@ -219,10 +241,13 @@ static int printf_to_env(void* env_pv, const char* format, ...) {
|
||||
}
|
||||
if (raw != NULL) {
|
||||
jstring output = (*env)->NewStringUTF(env, raw);
|
||||
(*env)->CallVoidMethod(env, denv->dis, denv->raw_print, denv->visitor, output);
|
||||
if ((*env)->ExceptionOccurred(env) != NULL) {
|
||||
if (!(*env)->ExceptionOccurred(env)) {
|
||||
/* make sure that UTF allocation doesn't cause OOM */
|
||||
(*env)->CallVoidMethod(env, denv->dis, denv->raw_print, denv->visitor, output);
|
||||
}
|
||||
if ((*env)->ExceptionOccurred(env)) {
|
||||
/* ignore exceptions for now */
|
||||
(*env)->ExceptionClear(env);
|
||||
(*env)->ExceptionClear(env);
|
||||
}
|
||||
return (int) flen;
|
||||
}
|
||||
@ -231,11 +256,16 @@ static int printf_to_env(void* env_pv, const char* format, ...) {
|
||||
va_end(ap);
|
||||
|
||||
output = (*env)->NewStringUTF(env, denv->buffer);
|
||||
(*env)->CallVoidMethod(env, denv->dis, denv->raw_print, denv->visitor, output);
|
||||
if ((*env)->ExceptionOccurred(env) != NULL) {
|
||||
if (!(*env)->ExceptionOccurred(env)) {
|
||||
/* make sure that UTF allocation doesn't cause OOM */
|
||||
(*env)->CallVoidMethod(env, denv->dis, denv->raw_print, denv->visitor, output);
|
||||
}
|
||||
|
||||
if ((*env)->ExceptionOccurred(env)) {
|
||||
/* ignore exceptions for now */
|
||||
(*env)->ExceptionClear(env);
|
||||
}
|
||||
|
||||
return cnt;
|
||||
}
|
||||
|
||||
@ -251,13 +281,24 @@ JNIEXPORT void JNICALL Java_sun_jvm_hotspot_asm_Disassembler_decode(JNIEnv * env
|
||||
jbyteArray code,
|
||||
jstring options_s,
|
||||
jlong decode_instructions_virtual) {
|
||||
jboolean isCopy;
|
||||
jbyte* start = (*env)->GetByteArrayElements(env, code, &isCopy);
|
||||
jbyte* end = start + (*env)->GetArrayLength(env, code);
|
||||
const char * options = (*env)->GetStringUTFChars(env, options_s, &isCopy);
|
||||
jclass disclass = (*env)->GetObjectClass(env, dis);
|
||||
|
||||
jbyte *start = NULL;
|
||||
jbyte *end = NULL;
|
||||
jclass disclass = NULL;
|
||||
const char *options = NULL;
|
||||
decode_env denv;
|
||||
|
||||
start = (*env)->GetByteArrayElements(env, code, NULL);
|
||||
if ((*env)->ExceptionOccurred(env)) {
|
||||
return;
|
||||
}
|
||||
end = start + (*env)->GetArrayLength(env, code);
|
||||
options = (*env)->GetStringUTFChars(env, options_s, NULL);
|
||||
if ((*env)->ExceptionOccurred(env)) {
|
||||
(*env)->ReleaseByteArrayElements(env, code, start, JNI_ABORT);
|
||||
return;
|
||||
}
|
||||
disclass = (*env)->GetObjectClass(env, dis);
|
||||
|
||||
denv.env = env;
|
||||
denv.dis = dis;
|
||||
denv.visitor = visitor;
|
||||
@ -266,6 +307,8 @@ JNIEXPORT void JNICALL Java_sun_jvm_hotspot_asm_Disassembler_decode(JNIEnv * env
|
||||
denv.handle_event = (*env)->GetMethodID(env, disclass, "handleEvent",
|
||||
"(Lsun/jvm/hotspot/asm/InstructionVisitor;Ljava/lang/String;J)J");
|
||||
if ((*env)->ExceptionOccurred(env)) {
|
||||
(*env)->ReleaseByteArrayElements(env, code, start, JNI_ABORT);
|
||||
(*env)->ReleaseStringUTFChars(env, options_s, options);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -273,11 +316,13 @@ JNIEXPORT void JNICALL Java_sun_jvm_hotspot_asm_Disassembler_decode(JNIEnv * env
|
||||
denv.raw_print = (*env)->GetMethodID(env, disclass, "rawPrint",
|
||||
"(Lsun/jvm/hotspot/asm/InstructionVisitor;Ljava/lang/String;)V");
|
||||
if ((*env)->ExceptionOccurred(env)) {
|
||||
(*env)->ReleaseByteArrayElements(env, code, start, JNI_ABORT);
|
||||
(*env)->ReleaseStringUTFChars(env, options_s, options);
|
||||
return;
|
||||
}
|
||||
|
||||
/* decode the buffer */
|
||||
(*(decode_func)(uintptr_t)decode_instructions_virtual)(startPc,
|
||||
(*(decode_func)(uintptr_t)decode_instructions_virtual)((uintptr_t) startPc,
|
||||
startPc + end - start,
|
||||
(unsigned char*)start,
|
||||
end - start,
|
||||
|
@ -89,8 +89,8 @@ int os::get_native_stack(address* stack, int frames, int toSkip) {
|
||||
} else {
|
||||
stack[frame_idx ++] = fr.pc();
|
||||
}
|
||||
if (fr.fp() == NULL || os::is_first_C_frame(&fr)
|
||||
||fr.sender_pc() == NULL || fr.cb() != NULL) break;
|
||||
if (fr.fp() == NULL || fr.cb() != NULL ||
|
||||
fr.sender_pc() == NULL || os::is_first_C_frame(&fr)) break;
|
||||
|
||||
if (fr.sender_pc() && !os::is_first_C_frame(&fr)) {
|
||||
fr = os::get_sender_for_C_frame(&fr);
|
||||
|
@ -3768,7 +3768,6 @@ HINSTANCE os::win32::load_Windows_dll(const char* name, char *ebuf,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#define MAX_EXIT_HANDLES PRODUCT_ONLY(32) NOT_PRODUCT(128)
|
||||
#define EXIT_TIMEOUT PRODUCT_ONLY(1000) NOT_PRODUCT(4000) /* 1 sec in product, 4 sec in debug */
|
||||
|
||||
static BOOL CALLBACK init_crit_sect_call(PINIT_ONCE, PVOID pcrit_sect, PVOID*) {
|
||||
@ -3787,7 +3786,7 @@ int os::win32::exit_process_or_thread(Ept what, int exit_code) {
|
||||
// _endthreadex().
|
||||
// Should be large enough to avoid blocking the exiting thread due to lack of
|
||||
// a free slot.
|
||||
static HANDLE handles[MAX_EXIT_HANDLES];
|
||||
static HANDLE handles[MAXIMUM_WAIT_OBJECTS];
|
||||
static int handle_count = 0;
|
||||
|
||||
static INIT_ONCE init_once_crit_sect = INIT_ONCE_STATIC_INIT;
|
||||
@ -3809,32 +3808,34 @@ int os::win32::exit_process_or_thread(Ept what, int exit_code) {
|
||||
if (res == WAIT_TIMEOUT) {
|
||||
handles[j++] = handles[i];
|
||||
} else {
|
||||
if (res != WAIT_OBJECT_0) {
|
||||
warning("WaitForSingleObject failed in %s: %d\n", __FILE__, __LINE__);
|
||||
// Don't keep the handle, if we failed waiting for it.
|
||||
if (res == WAIT_FAILED) {
|
||||
warning("WaitForSingleObject failed (%u) in %s: %d\n",
|
||||
GetLastError(), __FILE__, __LINE__);
|
||||
}
|
||||
// Don't keep the handle, if we failed waiting for it.
|
||||
CloseHandle(handles[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// If there's no free slot in the array of the kept handles, we'll have to
|
||||
// wait until at least one thread completes exiting.
|
||||
if ((handle_count = j) == MAX_EXIT_HANDLES) {
|
||||
if ((handle_count = j) == MAXIMUM_WAIT_OBJECTS) {
|
||||
// Raise the priority of the oldest exiting thread to increase its chances
|
||||
// to complete sooner.
|
||||
SetThreadPriority(handles[0], THREAD_PRIORITY_ABOVE_NORMAL);
|
||||
res = WaitForMultipleObjects(MAX_EXIT_HANDLES, handles, FALSE, EXIT_TIMEOUT);
|
||||
if (res >= WAIT_OBJECT_0 && res < (WAIT_OBJECT_0 + MAX_EXIT_HANDLES)) {
|
||||
res = WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, handles, FALSE, EXIT_TIMEOUT);
|
||||
if (res >= WAIT_OBJECT_0 && res < (WAIT_OBJECT_0 + MAXIMUM_WAIT_OBJECTS)) {
|
||||
i = (res - WAIT_OBJECT_0);
|
||||
handle_count = MAX_EXIT_HANDLES - 1;
|
||||
handle_count = MAXIMUM_WAIT_OBJECTS - 1;
|
||||
for (; i < handle_count; ++i) {
|
||||
handles[i] = handles[i + 1];
|
||||
}
|
||||
} else {
|
||||
warning("WaitForMultipleObjects %s in %s: %d\n",
|
||||
(res == WAIT_FAILED ? "failed" : "timed out"), __FILE__, __LINE__);
|
||||
warning("WaitForMultipleObjects %s (%u) in %s: %d\n",
|
||||
(res == WAIT_FAILED ? "failed" : "timed out"),
|
||||
GetLastError(), __FILE__, __LINE__);
|
||||
// Don't keep handles, if we failed waiting for them.
|
||||
for (i = 0; i < MAX_EXIT_HANDLES; ++i) {
|
||||
for (i = 0; i < MAXIMUM_WAIT_OBJECTS; ++i) {
|
||||
CloseHandle(handles[i]);
|
||||
}
|
||||
handle_count = 0;
|
||||
@ -3846,7 +3847,8 @@ int os::win32::exit_process_or_thread(Ept what, int exit_code) {
|
||||
hthr = GetCurrentThread();
|
||||
if (!DuplicateHandle(hproc, hthr, hproc, &handles[handle_count],
|
||||
0, FALSE, DUPLICATE_SAME_ACCESS)) {
|
||||
warning("DuplicateHandle failed in %s: %d\n", __FILE__, __LINE__);
|
||||
warning("DuplicateHandle failed (%u) in %s: %d\n",
|
||||
GetLastError(), __FILE__, __LINE__);
|
||||
} else {
|
||||
++handle_count;
|
||||
}
|
||||
@ -3869,9 +3871,10 @@ int os::win32::exit_process_or_thread(Ept what, int exit_code) {
|
||||
SetThreadPriority(handles[i], THREAD_PRIORITY_ABOVE_NORMAL);
|
||||
}
|
||||
res = WaitForMultipleObjects(handle_count, handles, TRUE, EXIT_TIMEOUT);
|
||||
if (res < WAIT_OBJECT_0 || res >= (WAIT_OBJECT_0 + MAX_EXIT_HANDLES)) {
|
||||
warning("WaitForMultipleObjects %s in %s: %d\n",
|
||||
(res == WAIT_FAILED ? "failed" : "timed out"), __FILE__, __LINE__);
|
||||
if (res == WAIT_FAILED || res == WAIT_TIMEOUT) {
|
||||
warning("WaitForMultipleObjects %s (%u) in %s: %d\n",
|
||||
(res == WAIT_FAILED ? "failed" : "timed out"),
|
||||
GetLastError(), __FILE__, __LINE__);
|
||||
}
|
||||
for (i = 0; i < handle_count; ++i) {
|
||||
CloseHandle(handles[i]);
|
||||
@ -3909,7 +3912,6 @@ int os::win32::exit_process_or_thread(Ept what, int exit_code) {
|
||||
return exit_code;
|
||||
}
|
||||
|
||||
#undef MAX_EXIT_HANDLES
|
||||
#undef EXIT_TIMEOUT
|
||||
|
||||
void os::win32::setmode_streams() {
|
||||
|
Loading…
x
Reference in New Issue
Block a user