Mercurial > hg > truffle
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 } |