comparison agent/src/os/bsd/MacosxDebuggerLocal.m @ 6782:5a98bf7d847b

6879063: SA should use hsdis for disassembly Summary: We should in SA to use hsdis for it like the JVM does to replace the current java based disassembler. Reviewed-by: twisti, jrose, sla Contributed-by: yumin.qi@oracle.com
author minqi
date Mon, 24 Sep 2012 12:44:00 -0700
parents 436b4a3231bf
children 758935f7c23f
comparison
equal deleted inserted replaced
6780:8440414b0fd8 6782:5a98bf7d847b
1 /* 1 /*
2 * Copyright (c) 2002, 2007, 2011, Oracle and/or its affiliates. All rights reserved. 2 * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 * 4 *
5 * This code is free software; you can redistribute it and/or modify it 5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as 6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. 7 * published by the Free Software Foundation.
29 #include <JavaVM/jni.h> 29 #include <JavaVM/jni.h>
30 30
31 #import <mach/mach.h> 31 #import <mach/mach.h>
32 #import <mach/mach_types.h> 32 #import <mach/mach_types.h>
33 #import <sys/sysctl.h> 33 #import <sys/sysctl.h>
34 #import <stdio.h>
35 #import <stdarg.h>
34 #import <stdlib.h> 36 #import <stdlib.h>
37 #import <strings.h>
38 #import <dlfcn.h>
39 #import <limits.h>
40 #import <errno.h>
35 41
36 jboolean debug = JNI_FALSE; 42 jboolean debug = JNI_FALSE;
37 43
38 static jfieldID symbolicatorID = 0; // set in _init0 44 static jfieldID symbolicatorID = 0; // set in _init0
39 static jfieldID taskID = 0; // set in _init0 45 static jfieldID taskID = 0; // set in _init0
58 64
59 #define CHECK_EXCEPTION_(value) if ((*env)->ExceptionOccurred(env)) { return value; } 65 #define CHECK_EXCEPTION_(value) if ((*env)->ExceptionOccurred(env)) { return value; }
60 #define CHECK_EXCEPTION if ((*env)->ExceptionOccurred(env)) { return;} 66 #define CHECK_EXCEPTION if ((*env)->ExceptionOccurred(env)) { return;}
61 #define THROW_NEW_DEBUGGER_EXCEPTION_(str, value) { throw_new_debugger_exception(env, str); return value; } 67 #define THROW_NEW_DEBUGGER_EXCEPTION_(str, value) { throw_new_debugger_exception(env, str); return value; }
62 #define THROW_NEW_DEBUGGER_EXCEPTION(str) { throw_new_debugger_exception(env, str); return;} 68 #define THROW_NEW_DEBUGGER_EXCEPTION(str) { throw_new_debugger_exception(env, str); return;}
69 #define CHECK_EXCEPTION_CLEAR if ((*env)->ExceptionOccurred(env)) { (*env)->ExceptionClear(env); }
70 #define CHECK_EXCEPTION_CLEAR_VOID if ((*env)->ExceptionOccurred(env)) { (*env)->ExceptionClear(env); return; }
71 #define CHECK_EXCEPTION_CLEAR_(value) if ((*env)->ExceptionOccurred(env)) { (*env)->ExceptionClear(env); return value; }
63 72
64 static void throw_new_debugger_exception(JNIEnv* env, const char* errMsg) { 73 static void throw_new_debugger_exception(JNIEnv* env, const char* errMsg) {
65 (*env)->ThrowNew(env, (*env)->FindClass(env, "sun/jvm/hotspot/debugger/DebuggerException"), errMsg); 74 (*env)->ThrowNew(env, (*env)->FindClass(env, "sun/jvm/hotspot/debugger/DebuggerException"), errMsg);
66 } 75 }
67 76
402 if (symbolicator != nil) { 411 if (symbolicator != nil) {
403 CFRelease(symbolicator); 412 CFRelease(symbolicator);
404 } 413 }
405 JNF_COCOA_EXIT(env); 414 JNF_COCOA_EXIT(env);
406 } 415 }
416
417 /*
418 * Class: sun_jvm_hotspot_asm_Disassembler
419 * Method: load_library
420 * Signature: (Ljava/lang/String;)L
421 */
422 JNIEXPORT jlong JNICALL Java_sun_jvm_hotspot_asm_Disassembler_load_1library(JNIEnv * env,
423 jclass disclass,
424 jstring jrepath_s,
425 jstring libname_s) {
426 uintptr_t func = 0;
427 const char* error_message = NULL;
428 const char* java_home;
429 jboolean isCopy;
430 uintptr_t *handle = NULL;
431
432 const char * jrepath = (*env)->GetStringUTFChars(env, jrepath_s, &isCopy); // like $JAVA_HOME/jre/lib/sparc/
433 const char * libname = (*env)->GetStringUTFChars(env, libname_s, &isCopy);
434 char buffer[128];
435
436 /* Load the hsdis library */
437 void* hsdis_handle;
438 hsdis_handle = dlopen(libname, RTLD_LAZY | RTLD_GLOBAL);
439 if (hsdis_handle == NULL) {
440 snprintf(buffer, sizeof(buffer), "%s%s", jrepath, libname);
441 hsdis_handle = dlopen(buffer, RTLD_LAZY | RTLD_GLOBAL);
442 }
443 if (hsdis_handle != NULL) {
444 func = (uintptr_t)dlsym(hsdis_handle, "decode_instructions_virtual");
445 }
446 if (func == 0) {
447 error_message = dlerror();
448 fprintf(stderr, "%s\n", error_message);
449 }
450
451 (*env)->ReleaseStringUTFChars(env, libname_s, libname);
452 (*env)->ReleaseStringUTFChars(env, jrepath_s, jrepath);
453
454 if (func == 0) {
455 /* Couldn't find entry point. error_message should contain some
456 * platform dependent error message.
457 */
458 THROW_NEW_DEBUGGER_EXCEPTION(error_message);
459 }
460 return (jlong)func;
461 }
462
463 /* signature of decode_instructions_virtual from hsdis.h */
464 typedef void* (*decode_func)(uintptr_t start_va, uintptr_t end_va,
465 unsigned char* start, uintptr_t length,
466 void* (*event_callback)(void*, const char*, void*),
467 void* event_stream,
468 int (*printf_callback)(void*, const char*, ...),
469 void* printf_stream,
470 const char* options);
471
472 /* container for call back state when decoding instructions */
473 typedef struct {
474 JNIEnv* env;
475 jobject dis;
476 jobject visitor;
477 jmethodID handle_event;
478 jmethodID raw_print;
479 char buffer[4096];
480 } decode_env;
481
482
483 /* event callback binding to Disassembler.handleEvent */
484 static void* event_to_env(void* env_pv, const char* event, void* arg) {
485 decode_env* denv = (decode_env*)env_pv;
486 JNIEnv* env = denv->env;
487 jstring event_string = (*env)->NewStringUTF(env, event);
488 jlong result = (*env)->CallLongMethod(env, denv->dis, denv->handle_event, denv->visitor,
489 event_string, (jlong) (uintptr_t)arg);
490 /* ignore exceptions for now */
491 CHECK_EXCEPTION_CLEAR_((void *)0);
492 return (void*)(uintptr_t)result;
493 }
494
495 /* printing callback binding to Disassembler.rawPrint */
496 static int printf_to_env(void* env_pv, const char* format, ...) {
497 jstring output;
498 va_list ap;
499 int cnt;
500 decode_env* denv = (decode_env*)env_pv;
501 JNIEnv* env = denv->env;
502 size_t flen = strlen(format);
503 const char* raw = NULL;
504
505 if (flen == 0) return 0;
506 if (flen < 2 ||
507 strchr(format, '%') == NULL) {
508 raw = format;
509 } else if (format[0] == '%' && format[1] == '%' &&
510 strchr(format+2, '%') == NULL) {
511 // happens a lot on machines with names like %foo
512 flen--;
513 raw = format+1;
514 }
515 if (raw != NULL) {
516 jstring output = (*env)->NewStringUTF(env, raw);
517 (*env)->CallVoidMethod(env, denv->dis, denv->raw_print, denv->visitor, output);
518 CHECK_EXCEPTION_CLEAR;
519 return (int) flen;
520 }
521 va_start(ap, format);
522 cnt = vsnprintf(denv->buffer, sizeof(denv->buffer), format, ap);
523 va_end(ap);
524
525 output = (*env)->NewStringUTF(env, denv->buffer);
526 (*env)->CallVoidMethod(env, denv->dis, denv->raw_print, denv->visitor, output);
527 CHECK_EXCEPTION_CLEAR;
528 return cnt;
529 }
530
531 /*
532 * Class: sun_jvm_hotspot_asm_Disassembler
533 * Method: decode
534 * Signature: (Lsun/jvm/hotspot/asm/InstructionVisitor;J[BLjava/lang/String;J)V
535 */
536 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_asm_Disassembler_decode(JNIEnv * env,
537 jobject dis,
538 jobject visitor,
539 jlong startPc,
540 jbyteArray code,
541 jstring options_s,
542 jlong decode_instructions_virtual) {
543 jboolean isCopy;
544 jbyte* start = (*env)->GetByteArrayElements(env, code, &isCopy);
545 jbyte* end = start + (*env)->GetArrayLength(env, code);
546 const char * options = (*env)->GetStringUTFChars(env, options_s, &isCopy);
547 jclass disclass = (*env)->GetObjectClass(env, dis);
548
549 decode_env denv;
550 denv.env = env;
551 denv.dis = dis;
552 denv.visitor = visitor;
553
554 /* find Disassembler.handleEvent callback */
555 denv.handle_event = (*env)->GetMethodID(env, disclass, "handleEvent",
556 "(Lsun/jvm/hotspot/asm/InstructionVisitor;Ljava/lang/String;J)J");
557 CHECK_EXCEPTION_CLEAR_VOID
558
559 /* find Disassembler.rawPrint callback */
560 denv.raw_print = (*env)->GetMethodID(env, disclass, "rawPrint",
561 "(Lsun/jvm/hotspot/asm/InstructionVisitor;Ljava/lang/String;)V");
562 CHECK_EXCEPTION_CLEAR_VOID
563
564 /* decode the buffer */
565 (*(decode_func)(uintptr_t)decode_instructions_virtual)(startPc,
566 startPc + end - start,
567 (unsigned char*)start,
568 end - start,
569 &event_to_env, (void*) &denv,
570 &printf_to_env, (void*) &denv,
571 options);
572
573 /* cleanup */
574 (*env)->ReleaseByteArrayElements(env, code, start, JNI_ABORT);
575 (*env)->ReleaseStringUTFChars(env, options_s, options);
576 }