agent/src/os/bsd/MacosxDebuggerLocal.m

Fri, 13 Jun 2014 18:04:49 -0700

author
ddehaven
date
Fri, 13 Jun 2014 18:04:49 -0700
changeset 7562
0e1aa319e805
parent 6437
f2294a37e723
child 7994
04ff2f6cd0eb
permissions
-rw-r--r--

8043340: [macosx] Fix hard-wired paths to JavaVM.framework
Summary: Build system tweaks to allow building on OS X 10.9 and later
Reviewed-by: erikj, dholmes

     1 /*
     2  * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     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
     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  */
    25 #include <objc/objc-runtime.h>
    26 #import <Foundation/Foundation.h>
    27 #import <JavaNativeFoundation/JavaNativeFoundation.h>
    29 #include <jni.h>
    31 #import <mach/mach.h>
    32 #import <mach/mach_types.h>
    33 #import <sys/sysctl.h>
    34 #import <stdio.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"
    45 #define UNSUPPORTED_ARCH "Unsupported architecture!"
    47 #if defined(x86_64) && !defined(amd64)
    48 #define amd64 1
    49 #endif
    51 #if amd64
    52 #include "sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext.h"
    53 #else
    54 #error UNSUPPORTED_ARCH
    55 #endif
    57 static jfieldID symbolicatorID = 0; // set in _init0
    58 static jfieldID taskID = 0; // set in _init0
    60 static jfieldID p_ps_prochandle_ID = 0;
    61 static jfieldID loadObjectList_ID = 0;
    62 static jmethodID listAdd_ID = 0;
    64 static jmethodID createClosestSymbol_ID = 0;
    65 static jmethodID createLoadObject_ID = 0;
    66 static jmethodID getJavaThreadsInfo_ID = 0;
    68 // indicator if thread id (lwpid_t) was set
    69 static bool _threads_filled = false;
    71 static void putSymbolicator(JNIEnv *env, jobject this_obj, id symbolicator) {
    72   (*env)->SetLongField(env, this_obj, symbolicatorID, (jlong)(intptr_t)symbolicator);
    73 }
    75 static id getSymbolicator(JNIEnv *env, jobject this_obj) {
    76   jlong ptr = (*env)->GetLongField(env, this_obj, symbolicatorID);
    77   return (id)(intptr_t)ptr;
    78 }
    80 static void putTask(JNIEnv *env, jobject this_obj, task_t task) {
    81   (*env)->SetLongField(env, this_obj, taskID, (jlong)task);
    82 }
    84 static task_t getTask(JNIEnv *env, jobject this_obj) {
    85   jlong ptr = (*env)->GetLongField(env, this_obj, taskID);
    86   return (task_t)ptr;
    87 }
    89 #define CHECK_EXCEPTION_(value) if ((*env)->ExceptionOccurred(env)) { return value; }
    90 #define CHECK_EXCEPTION if ((*env)->ExceptionOccurred(env)) { return;}
    91 #define THROW_NEW_DEBUGGER_EXCEPTION_(str, value) { throw_new_debugger_exception(env, str); return value; }
    92 #define THROW_NEW_DEBUGGER_EXCEPTION(str) { throw_new_debugger_exception(env, str); return;}
    93 #define CHECK_EXCEPTION_CLEAR if ((*env)->ExceptionOccurred(env)) { (*env)->ExceptionClear(env); } 
    94 #define CHECK_EXCEPTION_CLEAR_VOID if ((*env)->ExceptionOccurred(env)) { (*env)->ExceptionClear(env); return; } 
    95 #define CHECK_EXCEPTION_CLEAR_(value) if ((*env)->ExceptionOccurred(env)) { (*env)->ExceptionClear(env); return value; } 
    97 static void throw_new_debugger_exception(JNIEnv* env, const char* errMsg) {
    98   jclass exceptionClass = (*env)->FindClass(env, "sun/jvm/hotspot/debugger/DebuggerException");
    99   CHECK_EXCEPTION;
   100   (*env)->ThrowNew(env, exceptionClass, errMsg);
   101 }
   103 static struct ps_prochandle* get_proc_handle(JNIEnv* env, jobject this_obj) {
   104   jlong ptr = (*env)->GetLongField(env, this_obj, p_ps_prochandle_ID);
   105   return (struct ps_prochandle*)(intptr_t)ptr;
   106 }
   108 #if defined(__i386__)
   109     #define hsdb_thread_state_t     x86_thread_state32_t
   110     #define hsdb_float_state_t      x86_float_state32_t
   111     #define HSDB_THREAD_STATE       x86_THREAD_STATE32
   112     #define HSDB_FLOAT_STATE        x86_FLOAT_STATE32
   113     #define HSDB_THREAD_STATE_COUNT x86_THREAD_STATE32_COUNT
   114     #define HSDB_FLOAT_STATE_COUNT  x86_FLOAT_STATE32_COUNT
   115 #elif defined(__x86_64__)
   116     #define hsdb_thread_state_t     x86_thread_state64_t
   117     #define hsdb_float_state_t      x86_float_state64_t
   118     #define HSDB_THREAD_STATE       x86_THREAD_STATE64
   119     #define HSDB_FLOAT_STATE        x86_FLOAT_STATE64
   120     #define HSDB_THREAD_STATE_COUNT x86_THREAD_STATE64_COUNT
   121     #define HSDB_FLOAT_STATE_COUNT  x86_FLOAT_STATE64_COUNT
   122 #else
   123     #error UNSUPPORTED_ARCH
   124 #endif
   126 /*
   127  * Class:     sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
   128  * Method:    init0
   129  * Signature: ()V
   130  */
   131 JNIEXPORT void JNICALL 
   132 Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_init0(JNIEnv *env, jclass cls) {
   133   symbolicatorID = (*env)->GetFieldID(env, cls, "symbolicator", "J");
   134   CHECK_EXCEPTION;
   135   taskID = (*env)->GetFieldID(env, cls, "task", "J");
   136   CHECK_EXCEPTION;
   138   // for core file
   139   p_ps_prochandle_ID = (*env)->GetFieldID(env, cls, "p_ps_prochandle", "J");
   140   CHECK_EXCEPTION;
   141   loadObjectList_ID = (*env)->GetFieldID(env, cls, "loadObjectList", "Ljava/util/List;");
   142   CHECK_EXCEPTION;
   144   // methods we use
   145   createClosestSymbol_ID = (*env)->GetMethodID(env, cls, "createClosestSymbol",
   146                     "(Ljava/lang/String;J)Lsun/jvm/hotspot/debugger/cdbg/ClosestSymbol;");
   147   CHECK_EXCEPTION;
   148   createLoadObject_ID = (*env)->GetMethodID(env, cls, "createLoadObject",
   149                     "(Ljava/lang/String;JJ)Lsun/jvm/hotspot/debugger/cdbg/LoadObject;");
   150   CHECK_EXCEPTION;
   152   // java.util.List method we call
   153   jclass listClass = (*env)->FindClass(env, "java/util/List");
   154   CHECK_EXCEPTION;
   155   listAdd_ID = (*env)->GetMethodID(env, listClass, "add", "(Ljava/lang/Object;)Z");
   156   CHECK_EXCEPTION;
   157   getJavaThreadsInfo_ID = (*env)->GetMethodID(env, cls, "getJavaThreadsInfo",
   158                                                      "()[J");
   159   CHECK_EXCEPTION;
   161   init_libproc(getenv("LIBSAPROC_DEBUG") != NULL);
   162 }
   164 JNIEXPORT jint JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_getAddressSize
   165   (JNIEnv *env, jclass cls)
   166 {
   167 #ifdef _LP64
   168   return 8;
   169 #else
   170   #error UNSUPPORTED_ARCH
   171 #endif
   172 }
   174 /** called by Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_lookupByName0 */
   175 jlong lookupByNameIncore(
   176   JNIEnv *env, struct ps_prochandle *ph, jobject this_obj, jstring objectName, jstring symbolName)
   177 {
   178   const char *objectName_cstr, *symbolName_cstr;
   179   jlong addr;
   180   jboolean isCopy;
   181   objectName_cstr = NULL;
   182   if (objectName != NULL) {
   183     objectName_cstr = (*env)->GetStringUTFChars(env, objectName, &isCopy);
   184     CHECK_EXCEPTION_(0);
   185   }
   186   symbolName_cstr = (*env)->GetStringUTFChars(env, symbolName, &isCopy);
   187   CHECK_EXCEPTION_(0);
   189   print_debug("look for %s \n", symbolName_cstr);
   190   addr = (jlong) lookup_symbol(ph, objectName_cstr, symbolName_cstr);
   192   if (objectName_cstr != NULL) {
   193     (*env)->ReleaseStringUTFChars(env, objectName, objectName_cstr);
   194   }
   195   (*env)->ReleaseStringUTFChars(env, symbolName, symbolName_cstr);
   196   return addr;
   197 }
   199 /*
   200  * Class:     sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
   201  * Method:    lookupByName0
   202  * Signature: (Ljava/lang/String;Ljava/lang/String;)J
   203  */
   204 JNIEXPORT jlong JNICALL 
   205 Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_lookupByName0(
   206   JNIEnv *env, jobject this_obj, 
   207   jstring objectName, jstring symbolName) 
   208 {
   209   struct ps_prochandle* ph = get_proc_handle(env, this_obj);
   210   if (ph != NULL && ph->core != NULL) {
   211     return lookupByNameIncore(env, ph, this_obj, objectName, symbolName);
   212   }
   214   jlong address = 0;
   216 JNF_COCOA_ENTER(env);
   217   NSString *symbolNameString = JNFJavaToNSString(env, symbolName);
   219   print_debug("lookupInProcess called for %s\n", [symbolNameString UTF8String]);
   221   id symbolicator = getSymbolicator(env, this_obj);
   222   if (symbolicator != nil) {
   223     uint64_t (*dynamicCall)(id, SEL, NSString *) = (uint64_t (*)(id, SEL, NSString *))&objc_msgSend;
   224     address = (jlong) dynamicCall(symbolicator, @selector(addressForSymbol:), symbolNameString);
   225   }
   227   print_debug("address of symbol %s = %llx\n", [symbolNameString UTF8String], address);
   228 JNF_COCOA_EXIT(env);
   230   return address;
   231 }
   233 /*
   234  * Class:     sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
   235  * Method:    lookupByAddress0
   236  * Signature: (J)Lsun/jvm/hotspot/debugger/cdbg/ClosestSymbol;
   237  */
   238 JNIEXPORT jobject JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_lookupByAddress0
   239   (JNIEnv *env, jobject this_obj, jlong addr) {
   240   uintptr_t offset;
   241   const char* sym = NULL;
   242   jstring sym_string;
   244   struct ps_prochandle* ph = get_proc_handle(env, this_obj);
   245   if (ph != NULL && ph->core != NULL) {
   246     sym = symbol_for_pc(ph, (uintptr_t) addr, &offset);
   247     if (sym == NULL) return 0;
   248     sym_string = (*env)->NewStringUTF(env, sym);
   249     CHECK_EXCEPTION_(0);
   250     return (*env)->CallObjectMethod(env, this_obj, createClosestSymbol_ID,
   251                                                 sym_string, (jlong)offset);
   252   }
   253   return 0;
   254 }
   256 /** called from Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_readBytesFromProcess0 */
   257 jbyteArray readBytesFromCore(
   258   JNIEnv *env, struct ps_prochandle *ph, jobject this_obj, jlong addr, jlong numBytes)
   259 {
   260   jboolean isCopy;
   261   jbyteArray array;
   262   jbyte *bufPtr;
   263   ps_err_e err;
   265   array = (*env)->NewByteArray(env, numBytes);
   266   CHECK_EXCEPTION_(0);
   267   bufPtr = (*env)->GetByteArrayElements(env, array, &isCopy);
   268   CHECK_EXCEPTION_(0);
   270   err = ps_pread(ph, (psaddr_t) (uintptr_t)addr, bufPtr, numBytes);
   271   (*env)->ReleaseByteArrayElements(env, array, bufPtr, 0);
   272   return (err == PS_OK)? array : 0;
   273 }
   275 /*
   276  * Class:     sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
   277  * Method:    readBytesFromProcess0
   278  * Signature: (JJ)Lsun/jvm/hotspot/debugger/ReadResult;
   279  */
   280 JNIEXPORT jbyteArray JNICALL
   281 Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_readBytesFromProcess0(
   282   JNIEnv *env, jobject this_obj, 
   283   jlong addr, jlong numBytes) 
   284 {
   285   print_debug("readBytesFromProcess called. addr = %llx numBytes = %lld\n", addr, numBytes);
   287   // must allocate storage instead of using former parameter buf
   288   jbyteArray array;
   290   struct ps_prochandle* ph = get_proc_handle(env, this_obj);
   291   if (ph != NULL && ph->core != NULL) {
   292     return readBytesFromCore(env, ph, this_obj, addr, numBytes);
   293   }
   295   array = (*env)->NewByteArray(env, numBytes);
   296   CHECK_EXCEPTION_(0);
   298   unsigned long alignedAddress;
   299   unsigned long alignedLength = 0;
   300   kern_return_t result;
   301   vm_offset_t *pages;
   302   int *mapped;
   303   long pageCount;
   304   uint byteCount;
   305   int i;
   306   unsigned long remaining;
   308   alignedAddress = trunc_page(addr);
   309   if (addr != alignedAddress) {
   310     alignedLength += addr - alignedAddress;
   311   }
   312   alignedLength = round_page(numBytes);
   313   pageCount = alignedLength/vm_page_size;
   315   // Allocate storage for pages and flags.
   316   pages = malloc(pageCount * sizeof(vm_offset_t));
   317   mapped = calloc(pageCount, sizeof(int));
   319   task_t gTask = getTask(env, this_obj);
   320   // Try to read each of the pages.
   321   for (i = 0; i < pageCount; i++) {
   322     result = vm_read(gTask, alignedAddress + i*vm_page_size, vm_page_size, 
   323 		     &pages[i], &byteCount);
   324     mapped[i] = (result == KERN_SUCCESS); 
   325     // assume all failures are unmapped pages
   326   }
   328   print_debug("%ld pages\n", pageCount);
   330   remaining = numBytes;
   332   for (i = 0; i < pageCount; i++) {
   333     unsigned long len = vm_page_size;
   334     unsigned long start = 0;
   336     if (i == 0) {
   337       start = addr - alignedAddress;
   338       len = vm_page_size - start;
   339     }
   341     if (i == (pageCount - 1)) {
   342       len = remaining;
   343     }
   345     if (mapped[i]) {
   346       print_debug("page %d mapped (len %ld start %ld)\n", i, len, start);
   347       (*env)->SetByteArrayRegion(env, array, 0, len, ((jbyte *) pages[i] + start));
   348       vm_deallocate(mach_task_self(), pages[i], vm_page_size);
   349     }
   351     remaining -= len;
   352   }
   354   free (pages);
   355   free (mapped);
   356   return array;
   357 }
   359 /** Only used for core file reading, set thread_id for threads which is got after core file parsed.
   360   * Thread context is available in Mach-O core file but thread id is not. We can get thread id
   361   * from Threads which store all java threads information when they are created. Here we can identify
   362   * them as java threads by checking if a thread's rsp or rbp within a java thread's stack.
   363   * Note Macosx uses unique_thread_id which is different from other platforms though printed ids
   364   * are still pthread id. Function BsdDebuggerLocal.getJavaThreadsInfo returns an array of long
   365   * integers to host all java threads' id, stack_start, stack_end as:
   366   * [uid0, stack_start0, stack_end0, uid1, stack_start1, stack_end1, ...]
   367   *
   368   * The work cannot be done at init0 since Threads is not available yet(VM not initialized yet). 
   369   * This function should be called only once if succeeded
   370   */ 
   371 bool fill_java_threads(JNIEnv* env, jobject this_obj, struct ps_prochandle* ph) {
   372   int n = 0, i = 0, j;
   373   struct reg regs;
   375   jlongArray thrinfos = (*env)->CallObjectMethod(env, this_obj, getJavaThreadsInfo_ID);
   376   CHECK_EXCEPTION_(false);
   377   int len = (int)(*env)->GetArrayLength(env, thrinfos);
   378   uint64_t* cinfos = (uint64_t *)(*env)->GetLongArrayElements(env, thrinfos, NULL);
   379   CHECK_EXCEPTION_(false); 
   380   n = get_num_threads(ph);
   381   print_debug("fill_java_threads called, num_of_thread = %d\n", n);
   382   for (i = 0; i < n; i++) {
   383     if (!get_nth_lwp_regs(ph, i, &regs)) {
   384       print_debug("Could not get regs of thread %d, already set!\n", i);
   385       return false;
   386     }
   387     for (j = 0; j < len; j += 3) {
   388       lwpid_t  uid = cinfos[j];
   389       uint64_t beg = cinfos[j + 1];
   390       uint64_t end = cinfos[j + 2]; 
   391       if ((regs.r_rsp < end && regs.r_rsp >= beg) ||
   392           (regs.r_rbp < end && regs.r_rbp >= beg)) {
   393         set_lwp_id(ph, i, uid);
   394         break;
   395       }
   396     }
   397   }
   398   (*env)->ReleaseLongArrayElements(env, thrinfos, (jlong*)cinfos, 0);
   399   CHECK_EXCEPTION_(false);
   400   return true;
   401 }
   403 /* For core file only, called from
   404  * Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_getThreadIntegerRegisterSet0
   405  */
   406 jlongArray getThreadIntegerRegisterSetFromCore(JNIEnv *env, jobject this_obj, long lwp_id, struct ps_prochandle* ph) {
   407   if (!_threads_filled)  {
   408     if (!fill_java_threads(env, this_obj, ph)) {
   409       throw_new_debugger_exception(env, "Failed to fill in threads");
   410       return 0;
   411     } else {
   412       _threads_filled = true;
   413     }
   414   }
   416   struct reg gregs;
   417   jboolean isCopy;
   418   jlongArray array;
   419   jlong *regs;
   421   if (get_lwp_regs(ph, lwp_id, &gregs) != true) {
   422     THROW_NEW_DEBUGGER_EXCEPTION_("get_thread_regs failed for a lwp", 0);
   423   }
   425 #undef NPRGREG
   426 #undef REG_INDEX
   427 #if amd64
   428 #define NPRGREG sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_NPRGREG
   429 #define REG_INDEX(reg) sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_##reg
   431   array = (*env)->NewLongArray(env, NPRGREG);
   432   CHECK_EXCEPTION_(0);
   433   regs = (*env)->GetLongArrayElements(env, array, &isCopy);
   435   regs[REG_INDEX(R15)] = gregs.r_r15;
   436   regs[REG_INDEX(R14)] = gregs.r_r14;
   437   regs[REG_INDEX(R13)] = gregs.r_r13;
   438   regs[REG_INDEX(R12)] = gregs.r_r12;
   439   regs[REG_INDEX(RBP)] = gregs.r_rbp;
   440   regs[REG_INDEX(RBX)] = gregs.r_rbx;
   441   regs[REG_INDEX(R11)] = gregs.r_r11;
   442   regs[REG_INDEX(R10)] = gregs.r_r10;
   443   regs[REG_INDEX(R9)]  = gregs.r_r9;
   444   regs[REG_INDEX(R8)]  = gregs.r_r8;
   445   regs[REG_INDEX(RAX)] = gregs.r_rax;
   446   regs[REG_INDEX(RCX)] = gregs.r_rcx;
   447   regs[REG_INDEX(RDX)] = gregs.r_rdx;
   448   regs[REG_INDEX(RSI)] = gregs.r_rsi;
   449   regs[REG_INDEX(RDI)] = gregs.r_rdi;
   450   regs[REG_INDEX(RIP)] = gregs.r_rip;
   451   regs[REG_INDEX(CS)]  = gregs.r_cs;
   452   regs[REG_INDEX(RSP)] = gregs.r_rsp;
   453   regs[REG_INDEX(SS)]  = gregs.r_ss;
   454   regs[REG_INDEX(FSBASE)] = 0;
   455   regs[REG_INDEX(GSBASE)] = 0;
   456   regs[REG_INDEX(DS)] = gregs.r_ds;
   457   regs[REG_INDEX(ES)] = gregs.r_es;
   458   regs[REG_INDEX(FS)] = gregs.r_fs;
   459   regs[REG_INDEX(GS)] = gregs.r_gs;
   460   regs[REG_INDEX(TRAPNO)] = gregs.r_trapno;
   461   regs[REG_INDEX(RFL)]    = gregs.r_rflags;
   463 #endif /* amd64 */
   464   (*env)->ReleaseLongArrayElements(env, array, regs, JNI_COMMIT);
   465   return array;
   466 }
   468 /*
   469  * Lookup the thread_t that corresponds to the given thread_id.
   470  * The thread_id should be the result from calling thread_info() with THREAD_IDENTIFIER_INFO
   471  * and reading the m_ident_info.thread_id returned.
   472  * The returned thread_t is the mach send right to the kernel port for the corresponding thread.
   473  *
   474  * We cannot simply use the OSThread._thread_id field in the JVM. This is set to ::mach_thread_self()
   475  * in the VM, but that thread port is not valid for a remote debugger to access the thread.
   476  */
   477 thread_t
   478 lookupThreadFromThreadId(task_t task, jlong thread_id) {
   479   print_debug("lookupThreadFromThreadId thread_id=0x%llx\n", thread_id);
   481   thread_array_t thread_list = NULL;
   482   mach_msg_type_number_t thread_list_count = 0;
   483   thread_t result_thread = 0;
   484   int i;
   486   // get the list of all the send rights
   487   kern_return_t result = task_threads(task, &thread_list, &thread_list_count);
   488   if (result != KERN_SUCCESS) {
   489     print_debug("task_threads returned 0x%x\n", result);
   490     return 0;
   491   }
   493   for(i = 0 ; i < thread_list_count; i++) {
   494     thread_identifier_info_data_t m_ident_info;
   495     mach_msg_type_number_t count = THREAD_IDENTIFIER_INFO_COUNT;
   497     // get the THREAD_IDENTIFIER_INFO for the send right
   498     result = thread_info(thread_list[i], THREAD_IDENTIFIER_INFO, (thread_info_t) &m_ident_info, &count);
   499     if (result != KERN_SUCCESS) {
   500       print_debug("thread_info returned 0x%x\n", result);
   501       break;
   502     }
   504     // if this is the one we're looking for, return the send right
   505     if (thread_id == m_ident_info.thread_id)
   506     {
   507       result_thread = thread_list[i];
   508       break;
   509     }
   510   }
   512   vm_size_t thread_list_size = (vm_size_t) (thread_list_count * sizeof (thread_t));
   513   vm_deallocate(mach_task_self(), (vm_address_t) thread_list, thread_list_count);
   515   return result_thread;
   516 }
   519 /*
   520  * Class:     sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
   521  * Method:    getThreadIntegerRegisterSet0
   522  * Signature: (J)[J
   523  */
   524 JNIEXPORT jlongArray JNICALL 
   525 Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_getThreadIntegerRegisterSet0(
   526   JNIEnv *env, jobject this_obj, 
   527   jlong thread_id) 
   528 {
   529   print_debug("getThreadRegisterSet0 called\n");
   531   struct ps_prochandle* ph = get_proc_handle(env, this_obj);
   532   if (ph != NULL && ph->core != NULL) {
   533     return getThreadIntegerRegisterSetFromCore(env, this_obj, thread_id, ph);
   534   }
   536   kern_return_t result;
   537   thread_t tid;
   538   mach_msg_type_number_t count = HSDB_THREAD_STATE_COUNT;
   539   hsdb_thread_state_t state;
   540   jlongArray registerArray;
   541   jlong *primitiveArray;
   542   task_t gTask = getTask(env, this_obj);
   544   tid = lookupThreadFromThreadId(gTask, thread_id);
   546   result = thread_get_state(tid, HSDB_THREAD_STATE, (thread_state_t)&state, &count);
   548   if (result != KERN_SUCCESS) {
   549     print_error("getregs: thread_get_state(%d) failed (%d)\n", tid, result);
   550     return NULL;
   551   }
   553 #if amd64
   554 #define NPRGREG sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_NPRGREG
   555 #undef REG_INDEX
   556 #define REG_INDEX(reg) sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_##reg
   558   // 64 bit
   559   print_debug("Getting threads for a 64-bit process\n");
   560   registerArray = (*env)->NewLongArray(env, NPRGREG);
   561   CHECK_EXCEPTION_(0);
   562   primitiveArray = (*env)->GetLongArrayElements(env, registerArray, NULL);
   564   primitiveArray[REG_INDEX(R15)] = state.__r15;
   565   primitiveArray[REG_INDEX(R14)] = state.__r14;
   566   primitiveArray[REG_INDEX(R13)] = state.__r13;
   567   primitiveArray[REG_INDEX(R12)] = state.__r12;
   568   primitiveArray[REG_INDEX(R11)] = state.__r11;
   569   primitiveArray[REG_INDEX(R10)] = state.__r10;
   570   primitiveArray[REG_INDEX(R9)]  = state.__r9;
   571   primitiveArray[REG_INDEX(R8)]  = state.__r8;
   572   primitiveArray[REG_INDEX(RDI)] = state.__rdi;
   573   primitiveArray[REG_INDEX(RSI)] = state.__rsi;
   574   primitiveArray[REG_INDEX(RBP)] = state.__rbp;
   575   primitiveArray[REG_INDEX(RBX)] = state.__rbx;
   576   primitiveArray[REG_INDEX(RDX)] = state.__rdx;
   577   primitiveArray[REG_INDEX(RCX)] = state.__rcx;
   578   primitiveArray[REG_INDEX(RAX)] = state.__rax;
   579   primitiveArray[REG_INDEX(TRAPNO)] = 0;            // trapno, not used
   580   primitiveArray[REG_INDEX(ERR)]    = 0;            // err, not used 
   581   primitiveArray[REG_INDEX(RIP)] = state.__rip;
   582   primitiveArray[REG_INDEX(CS)]  = state.__cs;
   583   primitiveArray[REG_INDEX(RFL)] = state.__rflags;
   584   primitiveArray[REG_INDEX(RSP)] = state.__rsp;
   585   primitiveArray[REG_INDEX(SS)] = 0;                // We don't have SS
   586   primitiveArray[REG_INDEX(FS)] = state.__fs;
   587   primitiveArray[REG_INDEX(GS)] = state.__gs;
   588   primitiveArray[REG_INDEX(ES)] = 0;
   589   primitiveArray[REG_INDEX(DS)] = 0;
   590   primitiveArray[REG_INDEX(FSBASE)] = 0;
   591   primitiveArray[REG_INDEX(GSBASE)] = 0;
   592   print_debug("set registers\n");
   594   (*env)->ReleaseLongArrayElements(env, registerArray, primitiveArray, 0);
   596 #else
   597 #error UNSUPPORTED_ARCH
   598 #endif /* amd64 */
   600   return registerArray;
   601 }
   603 /*
   604  * Class:     sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
   605  * Method:    translateTID0
   606  * Signature: (I)I
   607  */
   608 JNIEXPORT jint JNICALL
   609 Java_sun_jvm_hotspot_debugger_macosx_MacOSXDebuggerLocal_translateTID0(
   610   JNIEnv *env, jobject this_obj, jint tid) 
   611 {
   612   print_debug("translateTID0 called on tid = 0x%x\n", (int)tid);
   614   kern_return_t result;
   615   thread_t foreign_tid, usable_tid;
   616   mach_msg_type_name_t type;
   618   foreign_tid = tid;
   620   task_t gTask = getTask(env, this_obj);
   621   result = mach_port_extract_right(gTask, foreign_tid, 
   622 				   MACH_MSG_TYPE_COPY_SEND, 
   623 				   &usable_tid, &type);
   624   if (result != KERN_SUCCESS)
   625     return -1;
   627   print_debug("translateTID0: 0x%x -> 0x%x\n", foreign_tid, usable_tid);
   629   return (jint) usable_tid;
   630 }
   633 static bool ptrace_continue(pid_t pid, int signal) {
   634   // pass the signal to the process so we don't swallow it
   635   int res;
   636   if ((res = ptrace(PT_CONTINUE, pid, (caddr_t)1, signal)) < 0) {
   637     print_error("attach: ptrace(PT_CONTINUE, %d) failed with %d\n", pid, res);
   638     return false;
   639   }
   640   return true;
   641 }
   643 // waits until the ATTACH has stopped the process
   644 // by signal SIGSTOP
   645 static bool ptrace_waitpid(pid_t pid) {
   646   int ret;
   647   int status;
   648   while (true) {
   649     // Wait for debuggee to stop.
   650     ret = waitpid(pid, &status, 0);
   651     if (ret >= 0) {
   652       if (WIFSTOPPED(status)) {
   653         // Any signal will stop the thread, make sure it is SIGSTOP. Otherwise SIGSTOP
   654         // will still be pending and delivered when the process is DETACHED and the process
   655         // will go to sleep.
   656         if (WSTOPSIG(status) == SIGSTOP) {
   657           // Debuggee stopped by SIGSTOP.
   658           return true;
   659         }
   660         if (!ptrace_continue(pid, WSTOPSIG(status))) {
   661           print_error("attach: Failed to correctly attach to VM. VM might HANG! [PTRACE_CONT failed, stopped by %d]\n", WSTOPSIG(status));
   662           return false;
   663         }
   664       } else {
   665         print_error("attach: waitpid(): Child process exited/terminated (status = 0x%x)\n", status);
   666         return false;
   667       }
   668     } else {
   669       switch (errno) {
   670         case EINTR:
   671           continue;
   672           break;
   673         case ECHILD:
   674           print_error("attach: waitpid() failed. Child process pid (%d) does not exist \n", pid);
   675           break;
   676         case EINVAL:
   677           print_error("attach: waitpid() failed. Invalid options argument.\n");
   678           break;
   679         default:
   680           print_error("attach: waitpid() failed. Unexpected error %d\n",errno);
   681           break;
   682       }
   683       return false;
   684     }
   685   }
   686 }
   688 // attach to a process/thread specified by "pid"
   689 static bool ptrace_attach(pid_t pid) {
   690   int res;
   691   if ((res = ptrace(PT_ATTACH, pid, 0, 0)) < 0) {
   692     print_error("ptrace(PT_ATTACH, %d) failed with %d\n", pid, res);
   693     return false;
   694   } else {
   695     return ptrace_waitpid(pid);
   696   }
   697 }
   699 /*
   700  * Class:     sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
   701  * Method:    attach0
   702  * Signature: (I)V
   703  */
   704 JNIEXPORT void JNICALL
   705 Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_attach0__I(
   706   JNIEnv *env, jobject this_obj, jint jpid)
   707 {
   708   print_debug("attach0 called for jpid=%d\n", (int)jpid);
   710 JNF_COCOA_ENTER(env);
   712   kern_return_t result;
   713   task_t gTask = 0;
   714   result = task_for_pid(mach_task_self(), jpid, &gTask);
   715   if (result != KERN_SUCCESS) {
   716     print_error("attach: task_for_pid(%d) failed: '%s' (%d)\n", (int)jpid, mach_error_string(result), result);
   717     THROW_NEW_DEBUGGER_EXCEPTION("Can't attach to the process. Could be caused by an incorrect pid or lack of privileges.");
   718   }
   719   putTask(env, this_obj, gTask);
   721   // use ptrace to stop the process
   722   // on os x, ptrace only needs to be called on the process, not the individual threads
   723   if (ptrace_attach(jpid) != true) {
   724     mach_port_deallocate(mach_task_self(), gTask);
   725     THROW_NEW_DEBUGGER_EXCEPTION("Can't attach to the process");
   726   }
   728   id symbolicator = nil;
   729   id jrsSymbolicator = objc_lookUpClass("JRSSymbolicator");
   730   if (jrsSymbolicator != nil) {
   731     id (*dynamicCall)(id, SEL, pid_t) = (id (*)(id, SEL, pid_t))&objc_msgSend;
   732     symbolicator = dynamicCall(jrsSymbolicator, @selector(symbolicatorForPid:), (pid_t)jpid);
   733   }
   734   if (symbolicator != nil) {
   735     CFRetain(symbolicator); // pin symbolicator while in java heap
   736   }
   738   putSymbolicator(env, this_obj, symbolicator);
   739   if (symbolicator == nil) {
   740     THROW_NEW_DEBUGGER_EXCEPTION("Can't attach symbolicator to the process");
   741   }
   743 JNF_COCOA_EXIT(env);
   744 }
   746 /** For core file, 
   747     called from Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_attach0__Ljava_lang_String_2Ljava_lang_String_2 */
   748 static void fillLoadObjects(JNIEnv* env, jobject this_obj, struct ps_prochandle* ph) {
   749   int n = 0, i = 0;
   751   // add load objects
   752   n = get_num_libs(ph);
   753   for (i = 0; i < n; i++) {
   754      uintptr_t base;
   755      const char* name;
   756      jobject loadObject;
   757      jobject loadObjectList;
   758      jstring nameString;
   760      base = get_lib_base(ph, i);
   761      name = get_lib_name(ph, i);
   762      nameString = (*env)->NewStringUTF(env, name);
   763      CHECK_EXCEPTION;
   764      loadObject = (*env)->CallObjectMethod(env, this_obj, createLoadObject_ID,
   765                                             nameString, (jlong)0, (jlong)base);
   766      CHECK_EXCEPTION;
   767      loadObjectList = (*env)->GetObjectField(env, this_obj, loadObjectList_ID);
   768      CHECK_EXCEPTION;
   769      (*env)->CallBooleanMethod(env, loadObjectList, listAdd_ID, loadObject);
   770      CHECK_EXCEPTION;
   771   }
   772 }
   774 /*
   775  * Class:     sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
   776  * Method:    attach0
   777  * Signature: (Ljava/lang/String;Ljava/lang/String;)V
   778  */
   779 JNIEXPORT void JNICALL
   780 Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_attach0__Ljava_lang_String_2Ljava_lang_String_2(
   781   JNIEnv *env, jobject this_obj, jstring execName, jstring coreName)
   782 {
   783   const char *execName_cstr;
   784   const char *coreName_cstr;
   785   jboolean isCopy;
   786   struct ps_prochandle* ph;
   788   execName_cstr = (*env)->GetStringUTFChars(env, execName, &isCopy);
   789   CHECK_EXCEPTION;
   790   coreName_cstr = (*env)->GetStringUTFChars(env, coreName, &isCopy);
   791   CHECK_EXCEPTION;
   793   print_debug("attach: %s %s\n", execName_cstr, coreName_cstr);
   795   if ( (ph = Pgrab_core(execName_cstr, coreName_cstr)) == NULL) {
   796     (*env)->ReleaseStringUTFChars(env, execName, execName_cstr);
   797     (*env)->ReleaseStringUTFChars(env, coreName, coreName_cstr);
   798     THROW_NEW_DEBUGGER_EXCEPTION("Can't attach to the core file");
   799   }
   800   (*env)->SetLongField(env, this_obj, p_ps_prochandle_ID, (jlong)(intptr_t)ph);
   801   (*env)->ReleaseStringUTFChars(env, execName, execName_cstr);
   802   (*env)->ReleaseStringUTFChars(env, coreName, coreName_cstr);
   803   fillLoadObjects(env, this_obj, ph);
   804 }
   806 /*
   807  * Class:     sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
   808  * Method:    detach0
   809  * Signature: ()V
   810  */
   811 JNIEXPORT void JNICALL
   812 Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_detach0(
   813   JNIEnv *env, jobject this_obj)
   814 {
   815   print_debug("detach0 called\n");
   816   struct ps_prochandle* ph = get_proc_handle(env, this_obj);
   817   if (ph != NULL && ph->core != NULL) {
   818      Prelease(ph);
   819      return;
   820   }
   821 JNF_COCOA_ENTER(env);
   822   task_t gTask = getTask(env, this_obj);
   824   // detach from the ptraced process causing it to resume execution
   825   int pid;
   826   kern_return_t k_res;
   827   k_res = pid_for_task(gTask, &pid);
   828   if (k_res != KERN_SUCCESS) {
   829     print_error("detach: pid_for_task(%d) failed (%d)\n", pid, k_res);
   830   }
   831   else {
   832     int res = ptrace(PT_DETACH, pid, 0, 0);
   833     if (res < 0) {
   834       print_error("detach: ptrace(PT_DETACH, %d) failed (%d)\n", pid, res);
   835     }
   836   }
   838   mach_port_deallocate(mach_task_self(), gTask);
   839   id symbolicator = getSymbolicator(env, this_obj);
   840   if (symbolicator != nil) {
   841     CFRelease(symbolicator);
   842   }
   843 JNF_COCOA_EXIT(env);
   844 }

mercurial