src/jdk.hotspot.agent/macosx/native/libsaproc/BsdDebuggerLocal.c
changeset 49274 9f3ce373370a
parent 49273 af8ab4f90a32
child 49275 c639a6b33c5c
equal deleted inserted replaced
49273:af8ab4f90a32 49274:9f3ce373370a
     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 <stdlib.h>
       
    26 #include <jni.h>
       
    27 #include "libproc.h"
       
    28 
       
    29 #if defined(x86_64) && !defined(amd64)
       
    30 #define amd64 1
       
    31 #endif
       
    32 
       
    33 #ifdef i386
       
    34 #include "sun_jvm_hotspot_debugger_x86_X86ThreadContext.h"
       
    35 #endif
       
    36 
       
    37 #ifdef amd64
       
    38 #include "sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext.h"
       
    39 #endif
       
    40 
       
    41 #if defined(sparc) || defined(sparcv9)
       
    42 #include "sun_jvm_hotspot_debugger_sparc_SPARCThreadContext.h"
       
    43 #endif
       
    44 
       
    45 static jfieldID p_ps_prochandle_ID = 0;
       
    46 static jfieldID threadList_ID = 0;
       
    47 static jfieldID loadObjectList_ID = 0;
       
    48 
       
    49 static jmethodID createClosestSymbol_ID = 0;
       
    50 static jmethodID createLoadObject_ID = 0;
       
    51 static jmethodID getThreadForThreadId_ID = 0;
       
    52 static jmethodID listAdd_ID = 0;
       
    53 
       
    54 #define CHECK_EXCEPTION_(value) if ((*env)->ExceptionOccurred(env)) { return value; }
       
    55 #define CHECK_EXCEPTION if ((*env)->ExceptionOccurred(env)) { return;}
       
    56 #define THROW_NEW_DEBUGGER_EXCEPTION_(str, value) { throw_new_debugger_exception(env, str); return value; }
       
    57 #define THROW_NEW_DEBUGGER_EXCEPTION(str) { throw_new_debugger_exception(env, str); return;}
       
    58 
       
    59 static void throw_new_debugger_exception(JNIEnv* env, const char* errMsg) {
       
    60   (*env)->ThrowNew(env, (*env)->FindClass(env, "sun/jvm/hotspot/debugger/DebuggerException"), errMsg);
       
    61 }
       
    62 
       
    63 static struct ps_prochandle* get_proc_handle(JNIEnv* env, jobject this_obj) {
       
    64   jlong ptr = (*env)->GetLongField(env, this_obj, p_ps_prochandle_ID);
       
    65   return (struct ps_prochandle*)(intptr_t)ptr;
       
    66 }
       
    67 
       
    68 /*
       
    69  * Class:     sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
       
    70  * Method:    init0
       
    71  * Signature: ()V
       
    72  */
       
    73 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_init0
       
    74   (JNIEnv *env, jclass cls) {
       
    75   jclass listClass;
       
    76 
       
    77   if (init_libproc(getenv("LIBSAPROC_DEBUG") != NULL) != true) {
       
    78      THROW_NEW_DEBUGGER_EXCEPTION("can't initialize libproc");
       
    79   }
       
    80 
       
    81   // fields we use
       
    82   p_ps_prochandle_ID = (*env)->GetFieldID(env, cls, "p_ps_prochandle", "J");
       
    83   CHECK_EXCEPTION;
       
    84   threadList_ID = (*env)->GetFieldID(env, cls, "threadList", "Ljava/util/List;");
       
    85   CHECK_EXCEPTION;
       
    86   loadObjectList_ID = (*env)->GetFieldID(env, cls, "loadObjectList", "Ljava/util/List;");
       
    87   CHECK_EXCEPTION;
       
    88 
       
    89   // methods we use
       
    90   createClosestSymbol_ID = (*env)->GetMethodID(env, cls, "createClosestSymbol",
       
    91                     "(Ljava/lang/String;J)Lsun/jvm/hotspot/debugger/cdbg/ClosestSymbol;");
       
    92   CHECK_EXCEPTION;
       
    93   createLoadObject_ID = (*env)->GetMethodID(env, cls, "createLoadObject",
       
    94                     "(Ljava/lang/String;JJ)Lsun/jvm/hotspot/debugger/cdbg/LoadObject;");
       
    95   CHECK_EXCEPTION;
       
    96   getThreadForThreadId_ID = (*env)->GetMethodID(env, cls, "getThreadForThreadId",
       
    97                                                      "(J)Lsun/jvm/hotspot/debugger/ThreadProxy;");
       
    98   CHECK_EXCEPTION;
       
    99   // java.util.List method we call
       
   100   listClass = (*env)->FindClass(env, "java/util/List");
       
   101   CHECK_EXCEPTION;
       
   102   listAdd_ID = (*env)->GetMethodID(env, listClass, "add", "(Ljava/lang/Object;)Z");
       
   103   CHECK_EXCEPTION;
       
   104 }
       
   105 
       
   106 JNIEXPORT jint JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_getAddressSize
       
   107   (JNIEnv *env, jclass cls)
       
   108 {
       
   109 #ifdef _LP64
       
   110  return 8;
       
   111 #else
       
   112  return 4;
       
   113 #endif
       
   114 
       
   115 }
       
   116 
       
   117 
       
   118 static void fillThreadsAndLoadObjects(JNIEnv* env, jobject this_obj, struct ps_prochandle* ph) {
       
   119   int n = 0, i = 0;
       
   120 
       
   121   // add threads
       
   122   n = get_num_threads(ph);
       
   123   for (i = 0; i < n; i++) {
       
   124     jobject thread;
       
   125     jobject threadList;
       
   126     lwpid_t lwpid;
       
   127 
       
   128     lwpid = get_lwp_id(ph, i);
       
   129     thread = (*env)->CallObjectMethod(env, this_obj, getThreadForThreadId_ID,
       
   130                                       (jlong)lwpid);
       
   131     CHECK_EXCEPTION;
       
   132     threadList = (*env)->GetObjectField(env, this_obj, threadList_ID);
       
   133     CHECK_EXCEPTION;
       
   134     (*env)->CallBooleanMethod(env, threadList, listAdd_ID, thread);
       
   135     CHECK_EXCEPTION;
       
   136   }
       
   137 
       
   138   // add load objects
       
   139   n = get_num_libs(ph);
       
   140   for (i = 0; i < n; i++) {
       
   141      uintptr_t base;
       
   142      const char* name;
       
   143      jobject loadObject;
       
   144      jobject loadObjectList;
       
   145 
       
   146      base = get_lib_base(ph, i);
       
   147      name = get_lib_name(ph, i);
       
   148      loadObject = (*env)->CallObjectMethod(env, this_obj, createLoadObject_ID,
       
   149                                    (*env)->NewStringUTF(env, name), (jlong)0, (jlong)base);
       
   150      CHECK_EXCEPTION;
       
   151      loadObjectList = (*env)->GetObjectField(env, this_obj, loadObjectList_ID);
       
   152      CHECK_EXCEPTION;
       
   153      (*env)->CallBooleanMethod(env, loadObjectList, listAdd_ID, loadObject);
       
   154      CHECK_EXCEPTION;
       
   155   }
       
   156 }
       
   157 
       
   158 /*
       
   159  * Class:     sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
       
   160  * Method:    attach0
       
   161  * Signature: (I)V
       
   162  */
       
   163 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_attach0__I
       
   164   (JNIEnv *env, jobject this_obj, jint jpid) {
       
   165 
       
   166   struct ps_prochandle* ph;
       
   167   if ( (ph = Pgrab(jpid)) == NULL) {
       
   168     THROW_NEW_DEBUGGER_EXCEPTION("Can't attach to the process");
       
   169   }
       
   170   (*env)->SetLongField(env, this_obj, p_ps_prochandle_ID, (jlong)(intptr_t)ph);
       
   171   fillThreadsAndLoadObjects(env, this_obj, ph);
       
   172 }
       
   173 
       
   174 /*
       
   175  * Class:     sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
       
   176  * Method:    attach0
       
   177  * Signature: (Ljava/lang/String;Ljava/lang/String;)V
       
   178  */
       
   179 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_attach0__Ljava_lang_String_2Ljava_lang_String_2
       
   180   (JNIEnv *env, jobject this_obj, jstring execName, jstring coreName) {
       
   181   const char *execName_cstr;
       
   182   const char *coreName_cstr;
       
   183   jboolean isCopy;
       
   184   struct ps_prochandle* ph;
       
   185 
       
   186   execName_cstr = (*env)->GetStringUTFChars(env, execName, &isCopy);
       
   187   CHECK_EXCEPTION;
       
   188   coreName_cstr = (*env)->GetStringUTFChars(env, coreName, &isCopy);
       
   189   CHECK_EXCEPTION;
       
   190 
       
   191   if ( (ph = Pgrab_core(execName_cstr, coreName_cstr)) == NULL) {
       
   192     (*env)->ReleaseStringUTFChars(env, execName, execName_cstr);
       
   193     (*env)->ReleaseStringUTFChars(env, coreName, coreName_cstr);
       
   194     THROW_NEW_DEBUGGER_EXCEPTION("Can't attach to the core file");
       
   195   }
       
   196   (*env)->SetLongField(env, this_obj, p_ps_prochandle_ID, (jlong)(intptr_t)ph);
       
   197   (*env)->ReleaseStringUTFChars(env, execName, execName_cstr);
       
   198   (*env)->ReleaseStringUTFChars(env, coreName, coreName_cstr);
       
   199   fillThreadsAndLoadObjects(env, this_obj, ph);
       
   200 }
       
   201 
       
   202 /*
       
   203  * Class:     sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
       
   204  * Method:    detach0
       
   205  * Signature: ()V
       
   206  */
       
   207 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_detach0
       
   208   (JNIEnv *env, jobject this_obj) {
       
   209   struct ps_prochandle* ph = get_proc_handle(env, this_obj);
       
   210   if (ph != NULL) {
       
   211      Prelease(ph);
       
   212   }
       
   213 }
       
   214 
       
   215 /*
       
   216  * Class:     sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
       
   217  * Method:    lookupByName0
       
   218  * Signature: (Ljava/lang/String;Ljava/lang/String;)J
       
   219  */
       
   220 JNIEXPORT jlong JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_lookupByName0
       
   221   (JNIEnv *env, jobject this_obj, jstring objectName, jstring symbolName) {
       
   222   const char *objectName_cstr, *symbolName_cstr;
       
   223   jlong addr;
       
   224   jboolean isCopy;
       
   225   struct ps_prochandle* ph = get_proc_handle(env, this_obj);
       
   226 
       
   227   objectName_cstr = NULL;
       
   228   if (objectName != NULL) {
       
   229     objectName_cstr = (*env)->GetStringUTFChars(env, objectName, &isCopy);
       
   230     CHECK_EXCEPTION_(0);
       
   231   }
       
   232   symbolName_cstr = (*env)->GetStringUTFChars(env, symbolName, &isCopy);
       
   233   CHECK_EXCEPTION_(0);
       
   234 
       
   235   addr = (jlong) lookup_symbol(ph, objectName_cstr, symbolName_cstr);
       
   236 
       
   237   if (objectName_cstr != NULL) {
       
   238     (*env)->ReleaseStringUTFChars(env, objectName, objectName_cstr);
       
   239   }
       
   240   (*env)->ReleaseStringUTFChars(env, symbolName, symbolName_cstr);
       
   241   return addr;
       
   242 }
       
   243 
       
   244 /*
       
   245  * Class:     sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
       
   246  * Method:    lookupByAddress0
       
   247  * Signature: (J)Lsun/jvm/hotspot/debugger/cdbg/ClosestSymbol;
       
   248  */
       
   249 JNIEXPORT jobject JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_lookupByAddress0
       
   250   (JNIEnv *env, jobject this_obj, jlong addr) {
       
   251   uintptr_t offset;
       
   252   const char* sym = NULL;
       
   253 
       
   254   struct ps_prochandle* ph = get_proc_handle(env, this_obj);
       
   255   sym = symbol_for_pc(ph, (uintptr_t) addr, &offset);
       
   256   if (sym == NULL) return 0;
       
   257   return (*env)->CallObjectMethod(env, this_obj, createClosestSymbol_ID,
       
   258                           (*env)->NewStringUTF(env, sym), (jlong)offset);
       
   259 }
       
   260 
       
   261 /*
       
   262  * Class:     sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
       
   263  * Method:    readBytesFromProcess0
       
   264  * Signature: (JJ)Lsun/jvm/hotspot/debugger/ReadResult;
       
   265  */
       
   266 JNIEXPORT jbyteArray JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_readBytesFromProcess0
       
   267   (JNIEnv *env, jobject this_obj, jlong addr, jlong numBytes) {
       
   268 
       
   269   jboolean isCopy;
       
   270   jbyteArray array;
       
   271   jbyte *bufPtr;
       
   272   ps_err_e err;
       
   273 
       
   274   array = (*env)->NewByteArray(env, numBytes);
       
   275   CHECK_EXCEPTION_(0);
       
   276   bufPtr = (*env)->GetByteArrayElements(env, array, &isCopy);
       
   277   CHECK_EXCEPTION_(0);
       
   278 
       
   279   err = ps_pread(get_proc_handle(env, this_obj), (psaddr_t) (uintptr_t)addr, bufPtr, numBytes);
       
   280   (*env)->ReleaseByteArrayElements(env, array, bufPtr, 0);
       
   281   return (err == PS_OK)? array : 0;
       
   282 }
       
   283 
       
   284 JNIEXPORT jlongArray JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_getThreadIntegerRegisterSet0
       
   285   (JNIEnv *env, jobject this_obj, jint lwp_id) {
       
   286 
       
   287   struct reg gregs;
       
   288   jboolean isCopy;
       
   289   jlongArray array;
       
   290   jlong *regs;
       
   291 
       
   292   struct ps_prochandle* ph = get_proc_handle(env, this_obj);
       
   293   if (get_lwp_regs(ph, lwp_id, &gregs) != true) {
       
   294      THROW_NEW_DEBUGGER_EXCEPTION_("get_thread_regs failed for a lwp", 0);
       
   295   }
       
   296 
       
   297 #undef NPRGREG
       
   298 #ifdef i386
       
   299 #define NPRGREG sun_jvm_hotspot_debugger_x86_X86ThreadContext_NPRGREG
       
   300 #endif
       
   301 #ifdef amd64
       
   302 #define NPRGREG sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_NPRGREG
       
   303 #endif
       
   304 #if defined(sparc) || defined(sparcv9)
       
   305 #define NPRGREG sun_jvm_hotspot_debugger_sparc_SPARCThreadContext_NPRGREG
       
   306 #endif
       
   307 
       
   308   array = (*env)->NewLongArray(env, NPRGREG);
       
   309   CHECK_EXCEPTION_(0);
       
   310   regs = (*env)->GetLongArrayElements(env, array, &isCopy);
       
   311 
       
   312 #undef REG_INDEX
       
   313 
       
   314 #ifdef i386
       
   315 #define REG_INDEX(reg) sun_jvm_hotspot_debugger_x86_X86ThreadContext_##reg
       
   316 
       
   317   regs[REG_INDEX(GS)]  = (uintptr_t) gregs.r_gs;
       
   318   regs[REG_INDEX(FS)]  = (uintptr_t) gregs.r_fs;
       
   319   regs[REG_INDEX(ES)]  = (uintptr_t) gregs.r_es;
       
   320   regs[REG_INDEX(DS)]  = (uintptr_t) gregs.r_ds;
       
   321   regs[REG_INDEX(EDI)] = (uintptr_t) gregs.r_edi;
       
   322   regs[REG_INDEX(ESI)] = (uintptr_t) gregs.r_esi;
       
   323   regs[REG_INDEX(FP)] = (uintptr_t) gregs.r_ebp;
       
   324   regs[REG_INDEX(SP)] = (uintptr_t) gregs.r_isp;
       
   325   regs[REG_INDEX(EBX)] = (uintptr_t) gregs.r_ebx;
       
   326   regs[REG_INDEX(EDX)] = (uintptr_t) gregs.r_edx;
       
   327   regs[REG_INDEX(ECX)] = (uintptr_t) gregs.r_ecx;
       
   328   regs[REG_INDEX(EAX)] = (uintptr_t) gregs.r_eax;
       
   329   regs[REG_INDEX(PC)] = (uintptr_t) gregs.r_eip;
       
   330   regs[REG_INDEX(CS)]  = (uintptr_t) gregs.r_cs;
       
   331   regs[REG_INDEX(SS)]  = (uintptr_t) gregs.r_ss;
       
   332 
       
   333 #endif /* i386 */
       
   334 
       
   335 #ifdef amd64
       
   336 #define REG_INDEX(reg) sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_##reg
       
   337 
       
   338   regs[REG_INDEX(R15)] = gregs.r_r15;
       
   339   regs[REG_INDEX(R14)] = gregs.r_r14;
       
   340   regs[REG_INDEX(R13)] = gregs.r_r13;
       
   341   regs[REG_INDEX(R12)] = gregs.r_r12;
       
   342   regs[REG_INDEX(RBP)] = gregs.r_rbp;
       
   343   regs[REG_INDEX(RBX)] = gregs.r_rbx;
       
   344   regs[REG_INDEX(R11)] = gregs.r_r11;
       
   345   regs[REG_INDEX(R10)] = gregs.r_r10;
       
   346   regs[REG_INDEX(R9)] = gregs.r_r9;
       
   347   regs[REG_INDEX(R8)] = gregs.r_r8;
       
   348   regs[REG_INDEX(RAX)] = gregs.r_rax;
       
   349   regs[REG_INDEX(RCX)] = gregs.r_rcx;
       
   350   regs[REG_INDEX(RDX)] = gregs.r_rdx;
       
   351   regs[REG_INDEX(RSI)] = gregs.r_rsi;
       
   352   regs[REG_INDEX(RDI)] = gregs.r_rdi;
       
   353   regs[REG_INDEX(RIP)] = gregs.r_rip;
       
   354   regs[REG_INDEX(CS)] = gregs.r_cs;
       
   355   regs[REG_INDEX(RSP)] = gregs.r_rsp;
       
   356   regs[REG_INDEX(SS)] = gregs.r_ss;
       
   357 //  regs[REG_INDEX(FSBASE)] = gregs.fs_base;
       
   358 //  regs[REG_INDEX(GSBASE)] = gregs.gs_base;
       
   359 //  regs[REG_INDEX(DS)] = gregs.ds;
       
   360 //  regs[REG_INDEX(ES)] = gregs.es;
       
   361 //  regs[REG_INDEX(FS)] = gregs.fs;
       
   362 //  regs[REG_INDEX(GS)] = gregs.gs;
       
   363 
       
   364 #endif /* amd64 */
       
   365 
       
   366 #if defined(sparc) || defined(sparcv9)
       
   367 
       
   368 #define REG_INDEX(reg) sun_jvm_hotspot_debugger_sparc_SPARCThreadContext_##reg
       
   369 
       
   370 #ifdef _LP64
       
   371   regs[REG_INDEX(R_PSR)] = gregs.tstate;
       
   372   regs[REG_INDEX(R_PC)]  = gregs.tpc;
       
   373   regs[REG_INDEX(R_nPC)] = gregs.tnpc;
       
   374   regs[REG_INDEX(R_Y)]   = gregs.y;
       
   375 #else
       
   376   regs[REG_INDEX(R_PSR)] = gregs.psr;
       
   377   regs[REG_INDEX(R_PC)]  = gregs.pc;
       
   378   regs[REG_INDEX(R_nPC)] = gregs.npc;
       
   379   regs[REG_INDEX(R_Y)]   = gregs.y;
       
   380 #endif
       
   381   regs[REG_INDEX(R_G0)]  =            0 ;
       
   382   regs[REG_INDEX(R_G1)]  = gregs.u_regs[0];
       
   383   regs[REG_INDEX(R_G2)]  = gregs.u_regs[1];
       
   384   regs[REG_INDEX(R_G3)]  = gregs.u_regs[2];
       
   385   regs[REG_INDEX(R_G4)]  = gregs.u_regs[3];
       
   386   regs[REG_INDEX(R_G5)]  = gregs.u_regs[4];
       
   387   regs[REG_INDEX(R_G6)]  = gregs.u_regs[5];
       
   388   regs[REG_INDEX(R_G7)]  = gregs.u_regs[6];
       
   389   regs[REG_INDEX(R_O0)]  = gregs.u_regs[7];
       
   390   regs[REG_INDEX(R_O1)]  = gregs.u_regs[8];
       
   391   regs[REG_INDEX(R_O2)]  = gregs.u_regs[ 9];
       
   392   regs[REG_INDEX(R_O3)]  = gregs.u_regs[10];
       
   393   regs[REG_INDEX(R_O4)]  = gregs.u_regs[11];
       
   394   regs[REG_INDEX(R_O5)]  = gregs.u_regs[12];
       
   395   regs[REG_INDEX(R_O6)]  = gregs.u_regs[13];
       
   396   regs[REG_INDEX(R_O7)]  = gregs.u_regs[14];
       
   397 #endif /* sparc */
       
   398 
       
   399 
       
   400   (*env)->ReleaseLongArrayElements(env, array, regs, JNI_COMMIT);
       
   401   return array;
       
   402 }