< prev index next >

src/jdk.hotspot.agent/macosx/native/libsaproc/MacosxDebuggerLocal.m

Print this page
rev 54099 : 8257988: Remove JNF dependency from libsaproc/MacosxDebuggerLocal.m
Reviewed-by: yan


   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *
  23  */
  24 
  25 #include <objc/objc-runtime.h>
  26 #import <Foundation/Foundation.h>
  27 #import <JavaNativeFoundation/JavaNativeFoundation.h>
  28 #import <JavaRuntimeSupport/JavaRuntimeSupport.h>
  29 
  30 #include <jni.h>
  31 
  32 #import <mach/mach.h>
  33 #import <mach/mach_types.h>
  34 #import <sys/sysctl.h>
  35 #import <stdio.h>
  36 #import <string.h>
  37 #import <stdarg.h>
  38 #import <stdlib.h>
  39 #import <strings.h>
  40 #import <dlfcn.h>
  41 #import <limits.h>
  42 #import <errno.h>
  43 #import <sys/types.h>
  44 #import <sys/ptrace.h>
  45 #include "libproc_impl.h"
  46 
  47 #define UNSUPPORTED_ARCH "Unsupported architecture!"
  48 


 243     CHECK_EXCEPTION_(0);
 244   }
 245   symbolName_cstr = (*env)->GetStringUTFChars(env, symbolName, &isCopy);
 246   if ((*env)->ExceptionOccurred(env)) {
 247     if (objectName_cstr != NULL) {
 248       (*env)->ReleaseStringUTFChars(env, objectName, objectName_cstr);
 249     }
 250     return 0;
 251   }
 252 
 253   print_debug("look for %s \n", symbolName_cstr);
 254   addr = (jlong) lookup_symbol(ph, objectName_cstr, symbolName_cstr);
 255 
 256   if (objectName_cstr != NULL) {
 257     (*env)->ReleaseStringUTFChars(env, objectName, objectName_cstr);
 258   }
 259   (*env)->ReleaseStringUTFChars(env, symbolName, symbolName_cstr);
 260   return addr;
 261 }
 262 

































 263 /*
 264  * Class:     sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
 265  * Method:    lookupByName0
 266  * Signature: (Ljava/lang/String;Ljava/lang/String;)J
 267  */
 268 JNIEXPORT jlong JNICALL
 269 Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_lookupByName0(
 270   JNIEnv *env, jobject this_obj,
 271   jstring objectName, jstring symbolName)
 272 {
 273   struct ps_prochandle* ph = get_proc_handle(env, this_obj);
 274   if (ph != NULL && ph->core != NULL) {
 275     return lookupByNameIncore(env, ph, this_obj, objectName, symbolName);
 276   }
 277 
 278   jlong address = 0;
 279 
 280 JNF_COCOA_ENTER(env);
 281   NSString *symbolNameString = JNFJavaToNSString(env, symbolName);

 282 
 283   print_debug("lookupInProcess called for %s\n", [symbolNameString UTF8String]);
 284 
 285   id symbolicator = getSymbolicator(env, this_obj);
 286   if (symbolicator != nil) {
 287     uint64_t (*dynamicCall)(id, SEL, NSString *) = (uint64_t (*)(id, SEL, NSString *))&objc_msgSend;
 288     address = (jlong) dynamicCall(symbolicator, @selector(addressForSymbol:), symbolNameString);
 289   }
 290 
 291   print_debug("address of symbol %s = %llx\n", [symbolNameString UTF8String], address);
 292 JNF_COCOA_EXIT(env);
 293 
 294   return address;
 295 }
 296 
 297 /*
 298  * Class:     sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
 299  * Method:    lookupByAddress0
 300  * Signature: (J)Lsun/jvm/hotspot/debugger/cdbg/ClosestSymbol;
 301  */
 302 JNIEXPORT jobject JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_lookupByAddress0
 303   (JNIEnv *env, jobject this_obj, jlong addr) {
 304   uintptr_t offset;
 305   const char* sym = NULL;
 306   jstring sym_string;
 307 
 308   struct ps_prochandle* ph = get_proc_handle(env, this_obj);
 309   if (ph != NULL && ph->core != NULL) {
 310     sym = symbol_for_pc(ph, (uintptr_t) addr, &offset);
 311     if (sym == NULL) return 0;
 312     sym_string = (*env)->NewStringUTF(env, sym);


 788   print_debug("reply msg from mach_exc_server: (msg->{bits = %#x, size = %u, "
 789               "remote_port = %#x, local_port = %#x, reserved = 0x%x, id = 0x%x},)",
 790               rep_msg.header.msgh_bits, rep_msg.header.msgh_size,
 791               rep_msg.header.msgh_remote_port, rep_msg.header.msgh_local_port,
 792               rep_msg.header.msgh_reserved, rep_msg.header.msgh_id);
 793 
 794   return true;
 795 }
 796 
 797 /*
 798  * Class:     sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
 799  * Method:    attach0
 800  * Signature: (I)V
 801  */
 802 JNIEXPORT void JNICALL
 803 Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_attach0__I(
 804   JNIEnv *env, jobject this_obj, jint jpid)
 805 {
 806   print_debug("attach0 called for jpid=%d\n", (int)jpid);
 807 
 808 JNF_COCOA_ENTER(env);
 809 
 810   kern_return_t result;
 811   task_t gTask = 0;
 812 
 813   result = task_for_pid(mach_task_self(), jpid, &gTask);
 814   if (result != KERN_SUCCESS) {
 815     print_error("attach: task_for_pid(%d) failed: '%s' (%d)\n", (int)jpid, mach_error_string(result), result);
 816     THROW_NEW_DEBUGGER_EXCEPTION(
 817       "Can't attach to the process. Could be caused by an incorrect pid or lack of privileges.");
 818   }
 819   putTask(env, this_obj, gTask);
 820 
 821   // Allocate an exception port.
 822   result = mach_port_allocate(mach_task_self(),
 823                               MACH_PORT_RIGHT_RECEIVE,
 824                               &tgt_exception_port);
 825   if (result != KERN_SUCCESS) {
 826     print_error("attach: mach_port_allocate() for tgt_exception_port failed: '%s' (%d)\n",
 827                 mach_error_string(result), result);
 828     THROW_NEW_DEBUGGER_EXCEPTION(


 902     THROW_NEW_DEBUGGER_EXCEPTION("Can't attach. Unable to suspend all the threads in the task.");
 903   }
 904 
 905   id symbolicator = nil;
 906   id jrsSymbolicator = objc_lookUpClass("JRSSymbolicator");
 907   if (jrsSymbolicator != nil) {
 908     id (*dynamicCall)(id, SEL, pid_t) = (id (*)(id, SEL, pid_t))&objc_msgSend;
 909     symbolicator = dynamicCall(jrsSymbolicator, @selector(symbolicatorForPid:), (pid_t)jpid);
 910   }
 911   if (symbolicator != nil) {
 912     CFRetain(symbolicator); // pin symbolicator while in java heap
 913   }
 914 
 915   putSymbolicator(env, this_obj, symbolicator);
 916   if (symbolicator == nil) {
 917     mach_port_deallocate(mach_task_self(), gTask);
 918     mach_port_deallocate(mach_task_self(), tgt_exception_port);
 919     THROW_NEW_DEBUGGER_EXCEPTION("Can't attach symbolicator to the process");
 920   }
 921 
 922 JNF_COCOA_EXIT(env);
 923 }
 924 
 925 /** For core file,
 926     called from Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_attach0__Ljava_lang_String_2Ljava_lang_String_2 */
 927 static void fillLoadObjects(JNIEnv* env, jobject this_obj, struct ps_prochandle* ph) {
 928   int n = 0, i = 0;
 929 
 930   // add load objects
 931   n = get_num_libs(ph);
 932   for (i = 0; i < n; i++) {
 933      uintptr_t base;
 934      const char* name;
 935      jobject loadObject;
 936      jobject loadObjectList;
 937      jstring nameString;
 938 
 939      base = get_lib_base(ph, i);
 940      name = get_lib_name(ph, i);
 941      nameString = (*env)->NewStringUTF(env, name);
 942      CHECK_EXCEPTION;


 996   if (throw_exception) {
 997     THROW_NEW_DEBUGGER_EXCEPTION("Cannot detach.");
 998   }
 999 }
1000 
1001 /*
1002  * Class:     sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
1003  * Method:    detach0
1004  * Signature: ()V
1005  */
1006 JNIEXPORT void JNICALL
1007 Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_detach0(
1008   JNIEnv *env, jobject this_obj)
1009 {
1010   print_debug("detach0 called\n");
1011   struct ps_prochandle* ph = get_proc_handle(env, this_obj);
1012   if (ph != NULL && ph->core != NULL) {
1013      Prelease(ph);
1014      return;
1015   }
1016 JNF_COCOA_ENTER(env);

1017 
1018   task_t gTask = getTask(env, this_obj);
1019   kern_return_t k_res = 0;
1020 
1021   // Restore the pre-saved original exception ports registered with the target process
1022   for (uint32_t i = 0; i < exception_saved_state.saved_exception_types_count; ++i) {
1023     k_res = task_set_exception_ports(gTask,
1024                                      exception_saved_state.saved_masks[i],
1025                                      exception_saved_state.saved_ports[i],
1026                                      exception_saved_state.saved_behaviors[i],
1027                                      exception_saved_state.saved_flavors[i]);
1028     if (k_res != KERN_SUCCESS) {
1029       print_error("detach: task_set_exception_ports failed with %d while "
1030                   "restoring the target exception ports.\n", k_res);
1031       detach_cleanup(gTask, env, this_obj, true);
1032     }
1033   }
1034 
1035   // detach from the ptraced process causing it to resume execution
1036   int pid;


1047       detach_cleanup(gTask, env, this_obj, true);
1048     }
1049   }
1050 
1051   // reply to the previous exception message
1052   k_res = mach_msg(&rep_msg.header,
1053                    MACH_SEND_MSG| MACH_SEND_INTERRUPT,
1054                    rep_msg.header.msgh_size,
1055                    0,
1056                    MACH_PORT_NULL,
1057                    MACH_MSG_TIMEOUT_NONE,
1058                    MACH_PORT_NULL);
1059   if (k_res != MACH_MSG_SUCCESS) {
1060     print_error("detach: mach_msg() for replying to pending exceptions failed: '%s' (%d)\n",
1061                  mach_error_string(k_res), k_res);
1062     detach_cleanup(gTask, env, this_obj, true);
1063   }
1064 
1065   detach_cleanup(gTask, env, this_obj, false);
1066 
1067 JNF_COCOA_EXIT(env);
1068 }


   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *
  23  */
  24 
  25 #include <objc/objc-runtime.h>
  26 #import <Foundation/Foundation.h>


  27 
  28 #include <jni.h>
  29 
  30 #import <mach/mach.h>
  31 #import <mach/mach_types.h>
  32 #import <sys/sysctl.h>
  33 #import <stdio.h>
  34 #import <string.h>
  35 #import <stdarg.h>
  36 #import <stdlib.h>
  37 #import <strings.h>
  38 #import <dlfcn.h>
  39 #import <limits.h>
  40 #import <errno.h>
  41 #import <sys/types.h>
  42 #import <sys/ptrace.h>
  43 #include "libproc_impl.h"
  44 
  45 #define UNSUPPORTED_ARCH "Unsupported architecture!"
  46 


 241     CHECK_EXCEPTION_(0);
 242   }
 243   symbolName_cstr = (*env)->GetStringUTFChars(env, symbolName, &isCopy);
 244   if ((*env)->ExceptionOccurred(env)) {
 245     if (objectName_cstr != NULL) {
 246       (*env)->ReleaseStringUTFChars(env, objectName, objectName_cstr);
 247     }
 248     return 0;
 249   }
 250 
 251   print_debug("look for %s \n", symbolName_cstr);
 252   addr = (jlong) lookup_symbol(ph, objectName_cstr, symbolName_cstr);
 253 
 254   if (objectName_cstr != NULL) {
 255     (*env)->ReleaseStringUTFChars(env, objectName, objectName_cstr);
 256   }
 257   (*env)->ReleaseStringUTFChars(env, symbolName, symbolName_cstr);
 258   return addr;
 259 }
 260 
 261 /* Create a pool and initiate a try block to catch any exception */
 262 #define JNI_COCOA_ENTER(env) \
 263  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; \
 264  @try {
 265 
 266 /* Don't allow NSExceptions to escape to Java.
 267  * If there is a Java exception that has been thrown that should escape.
 268  * And ensure we drain the auto-release pool.
 269  */
 270 #define JNI_COCOA_EXIT(env) \
 271  } \
 272  @catch (NSException *e) { \
 273      NSLog(@"%@", [e callStackSymbols]); \
 274  } \
 275  @finally { \
 276     [pool drain]; \
 277  };
 278 
 279 static NSString* JavaStringToNSString(JNIEnv *env, jstring jstr) {
 280 
 281     if (jstr == NULL) {
 282         return NULL;
 283     }
 284     jsize len = (*env)->GetStringLength(env, jstr);
 285     const jchar *chars = (*env)->GetStringChars(env, jstr, NULL);
 286     if (chars == NULL) {
 287         return NULL;
 288     }
 289     NSString *result = [NSString stringWithCharacters:(UniChar *)chars length:len];
 290     (*env)->ReleaseStringChars(env, jstr, chars);
 291     return result;
 292 }
 293 
 294 /*
 295  * Class:     sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
 296  * Method:    lookupByName0
 297  * Signature: (Ljava/lang/String;Ljava/lang/String;)J
 298  */
 299 JNIEXPORT jlong JNICALL
 300 Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_lookupByName0(
 301   JNIEnv *env, jobject this_obj,
 302   jstring objectName, jstring symbolName)
 303 {
 304   struct ps_prochandle* ph = get_proc_handle(env, this_obj);
 305   if (ph != NULL && ph->core != NULL) {
 306     return lookupByNameIncore(env, ph, this_obj, objectName, symbolName);
 307   }
 308 
 309   jlong address = 0;
 310 
 311   JNI_COCOA_ENTER(env);
 312 
 313   NSString *symbolNameString = JavaStringToNSString(env, symbolName);
 314 
 315   print_debug("lookupInProcess called for %s\n", [symbolNameString UTF8String]);
 316 
 317   id symbolicator = getSymbolicator(env, this_obj);
 318   if (symbolicator != nil) {
 319     uint64_t (*dynamicCall)(id, SEL, NSString *) = (uint64_t (*)(id, SEL, NSString *))&objc_msgSend;
 320     address = (jlong) dynamicCall(symbolicator, @selector(addressForSymbol:), symbolNameString);
 321   }
 322 
 323   print_debug("address of symbol %s = %llx\n", [symbolNameString UTF8String], address);
 324   JNI_COCOA_EXIT(env);
 325 
 326   return address;
 327 }
 328 
 329 /*
 330  * Class:     sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
 331  * Method:    lookupByAddress0
 332  * Signature: (J)Lsun/jvm/hotspot/debugger/cdbg/ClosestSymbol;
 333  */
 334 JNIEXPORT jobject JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_lookupByAddress0
 335   (JNIEnv *env, jobject this_obj, jlong addr) {
 336   uintptr_t offset;
 337   const char* sym = NULL;
 338   jstring sym_string;
 339 
 340   struct ps_prochandle* ph = get_proc_handle(env, this_obj);
 341   if (ph != NULL && ph->core != NULL) {
 342     sym = symbol_for_pc(ph, (uintptr_t) addr, &offset);
 343     if (sym == NULL) return 0;
 344     sym_string = (*env)->NewStringUTF(env, sym);


 820   print_debug("reply msg from mach_exc_server: (msg->{bits = %#x, size = %u, "
 821               "remote_port = %#x, local_port = %#x, reserved = 0x%x, id = 0x%x},)",
 822               rep_msg.header.msgh_bits, rep_msg.header.msgh_size,
 823               rep_msg.header.msgh_remote_port, rep_msg.header.msgh_local_port,
 824               rep_msg.header.msgh_reserved, rep_msg.header.msgh_id);
 825 
 826   return true;
 827 }
 828 
 829 /*
 830  * Class:     sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
 831  * Method:    attach0
 832  * Signature: (I)V
 833  */
 834 JNIEXPORT void JNICALL
 835 Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_attach0__I(
 836   JNIEnv *env, jobject this_obj, jint jpid)
 837 {
 838   print_debug("attach0 called for jpid=%d\n", (int)jpid);
 839 
 840   JNI_COCOA_ENTER(env);
 841 
 842   kern_return_t result;
 843   task_t gTask = 0;
 844 
 845   result = task_for_pid(mach_task_self(), jpid, &gTask);
 846   if (result != KERN_SUCCESS) {
 847     print_error("attach: task_for_pid(%d) failed: '%s' (%d)\n", (int)jpid, mach_error_string(result), result);
 848     THROW_NEW_DEBUGGER_EXCEPTION(
 849       "Can't attach to the process. Could be caused by an incorrect pid or lack of privileges.");
 850   }
 851   putTask(env, this_obj, gTask);
 852 
 853   // Allocate an exception port.
 854   result = mach_port_allocate(mach_task_self(),
 855                               MACH_PORT_RIGHT_RECEIVE,
 856                               &tgt_exception_port);
 857   if (result != KERN_SUCCESS) {
 858     print_error("attach: mach_port_allocate() for tgt_exception_port failed: '%s' (%d)\n",
 859                 mach_error_string(result), result);
 860     THROW_NEW_DEBUGGER_EXCEPTION(


 934     THROW_NEW_DEBUGGER_EXCEPTION("Can't attach. Unable to suspend all the threads in the task.");
 935   }
 936 
 937   id symbolicator = nil;
 938   id jrsSymbolicator = objc_lookUpClass("JRSSymbolicator");
 939   if (jrsSymbolicator != nil) {
 940     id (*dynamicCall)(id, SEL, pid_t) = (id (*)(id, SEL, pid_t))&objc_msgSend;
 941     symbolicator = dynamicCall(jrsSymbolicator, @selector(symbolicatorForPid:), (pid_t)jpid);
 942   }
 943   if (symbolicator != nil) {
 944     CFRetain(symbolicator); // pin symbolicator while in java heap
 945   }
 946 
 947   putSymbolicator(env, this_obj, symbolicator);
 948   if (symbolicator == nil) {
 949     mach_port_deallocate(mach_task_self(), gTask);
 950     mach_port_deallocate(mach_task_self(), tgt_exception_port);
 951     THROW_NEW_DEBUGGER_EXCEPTION("Can't attach symbolicator to the process");
 952   }
 953 
 954   JNI_COCOA_EXIT(env);
 955 }
 956 
 957 /** For core file,
 958     called from Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_attach0__Ljava_lang_String_2Ljava_lang_String_2 */
 959 static void fillLoadObjects(JNIEnv* env, jobject this_obj, struct ps_prochandle* ph) {
 960   int n = 0, i = 0;
 961 
 962   // add load objects
 963   n = get_num_libs(ph);
 964   for (i = 0; i < n; i++) {
 965      uintptr_t base;
 966      const char* name;
 967      jobject loadObject;
 968      jobject loadObjectList;
 969      jstring nameString;
 970 
 971      base = get_lib_base(ph, i);
 972      name = get_lib_name(ph, i);
 973      nameString = (*env)->NewStringUTF(env, name);
 974      CHECK_EXCEPTION;


1028   if (throw_exception) {
1029     THROW_NEW_DEBUGGER_EXCEPTION("Cannot detach.");
1030   }
1031 }
1032 
1033 /*
1034  * Class:     sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
1035  * Method:    detach0
1036  * Signature: ()V
1037  */
1038 JNIEXPORT void JNICALL
1039 Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_detach0(
1040   JNIEnv *env, jobject this_obj)
1041 {
1042   print_debug("detach0 called\n");
1043   struct ps_prochandle* ph = get_proc_handle(env, this_obj);
1044   if (ph != NULL && ph->core != NULL) {
1045      Prelease(ph);
1046      return;
1047   }
1048 
1049   JNI_COCOA_ENTER(env);
1050 
1051   task_t gTask = getTask(env, this_obj);
1052   kern_return_t k_res = 0;
1053 
1054   // Restore the pre-saved original exception ports registered with the target process
1055   for (uint32_t i = 0; i < exception_saved_state.saved_exception_types_count; ++i) {
1056     k_res = task_set_exception_ports(gTask,
1057                                      exception_saved_state.saved_masks[i],
1058                                      exception_saved_state.saved_ports[i],
1059                                      exception_saved_state.saved_behaviors[i],
1060                                      exception_saved_state.saved_flavors[i]);
1061     if (k_res != KERN_SUCCESS) {
1062       print_error("detach: task_set_exception_ports failed with %d while "
1063                   "restoring the target exception ports.\n", k_res);
1064       detach_cleanup(gTask, env, this_obj, true);
1065     }
1066   }
1067 
1068   // detach from the ptraced process causing it to resume execution
1069   int pid;


1080       detach_cleanup(gTask, env, this_obj, true);
1081     }
1082   }
1083 
1084   // reply to the previous exception message
1085   k_res = mach_msg(&rep_msg.header,
1086                    MACH_SEND_MSG| MACH_SEND_INTERRUPT,
1087                    rep_msg.header.msgh_size,
1088                    0,
1089                    MACH_PORT_NULL,
1090                    MACH_MSG_TIMEOUT_NONE,
1091                    MACH_PORT_NULL);
1092   if (k_res != MACH_MSG_SUCCESS) {
1093     print_error("detach: mach_msg() for replying to pending exceptions failed: '%s' (%d)\n",
1094                  mach_error_string(k_res), k_res);
1095     detach_cleanup(gTask, env, this_obj, true);
1096   }
1097 
1098   detach_cleanup(gTask, env, this_obj, false);
1099 
1100   JNI_COCOA_EXIT(env);
1101 }
< prev index next >