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