hotspot/src/jdk.hotspot.agent/solaris/native/libsaproc/saproc.cpp
changeset 35217 ce4b5303a813
parent 26410 a34c8032e674
child 42035 10e6e31dc1aa
equal deleted inserted replaced
35216:71c463a17b3b 35217:ce4b5303a813
       
     1 /*
       
     2  * Copyright (c) 2002, 2013, 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 "salibproc.h"
       
    26 #include "sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal.h"
       
    27 #ifndef SOLARIS_11_B159_OR_LATER
       
    28 #include <sys/utsname.h>
       
    29 #endif
       
    30 #include <thread_db.h>
       
    31 #include <strings.h>
       
    32 #include <limits.h>
       
    33 #include <demangle.h>
       
    34 #include <stdarg.h>
       
    35 #include <stdlib.h>
       
    36 #include <errno.h>
       
    37 
       
    38 #define CHECK_EXCEPTION_(value) if(env->ExceptionOccurred()) { return value; }
       
    39 #define CHECK_EXCEPTION if(env->ExceptionOccurred()) { return;}
       
    40 #define THROW_NEW_DEBUGGER_EXCEPTION_(str, value) { throwNewDebuggerException(env, str); return value; }
       
    41 #define THROW_NEW_DEBUGGER_EXCEPTION(str) { throwNewDebuggerException(env, str); return;}
       
    42 
       
    43 #define SYMBOL_BUF_SIZE  256
       
    44 #define ERR_MSG_SIZE     (PATH_MAX + 256)
       
    45 
       
    46 // debug modes
       
    47 static int _libsaproc_debug = 0;
       
    48 #ifndef SOLARIS_11_B159_OR_LATER
       
    49 static bool _Pstack_iter_debug = false;
       
    50 
       
    51 static void dprintf_2(const char* format,...) {
       
    52   if (_Pstack_iter_debug) {
       
    53     va_list alist;
       
    54 
       
    55     va_start(alist, format);
       
    56     fputs("Pstack_iter DEBUG: ", stderr);
       
    57     vfprintf(stderr, format, alist);
       
    58     va_end(alist);
       
    59   }
       
    60 }
       
    61 #endif // !SOLARIS_11_B159_OR_LATER
       
    62 
       
    63 static void print_debug(const char* format,...) {
       
    64   if (_libsaproc_debug) {
       
    65     va_list alist;
       
    66 
       
    67     va_start(alist, format);
       
    68     fputs("libsaproc DEBUG: ", stderr);
       
    69     vfprintf(stderr, format, alist);
       
    70     va_end(alist);
       
    71   }
       
    72 }
       
    73 
       
    74 struct Debugger {
       
    75     JNIEnv* env;
       
    76     jobject this_obj;
       
    77 };
       
    78 
       
    79 struct DebuggerWithObject : Debugger {
       
    80     jobject obj;
       
    81 };
       
    82 
       
    83 struct DebuggerWith2Objects : DebuggerWithObject {
       
    84     jobject obj2;
       
    85 };
       
    86 
       
    87 /*
       
    88 * Portions of user thread level detail gathering code is from pstack source
       
    89 * code. See pstack.c in Solaris 2.8 user commands source code.
       
    90 */
       
    91 
       
    92 static void throwNewDebuggerException(JNIEnv* env, const char* errMsg) {
       
    93   jclass clazz = env->FindClass("sun/jvm/hotspot/debugger/DebuggerException");
       
    94   CHECK_EXCEPTION;
       
    95   env->ThrowNew(clazz, errMsg);
       
    96 }
       
    97 
       
    98 // JNI ids for some fields, methods
       
    99 
       
   100 // libproc handler pointer
       
   101 static jfieldID p_ps_prochandle_ID = 0;
       
   102 
       
   103 // libthread.so dlopen handle, thread agent ptr and function pointers
       
   104 static jfieldID libthread_db_handle_ID   = 0;
       
   105 static jfieldID p_td_thragent_t_ID       = 0;
       
   106 static jfieldID p_td_init_ID             = 0;
       
   107 static jfieldID p_td_ta_new_ID           = 0;
       
   108 static jfieldID p_td_ta_delete_ID        = 0;
       
   109 static jfieldID p_td_ta_thr_iter_ID      = 0;
       
   110 static jfieldID p_td_thr_get_info_ID     = 0;
       
   111 static jfieldID p_td_ta_map_id2thr_ID    = 0;
       
   112 static jfieldID p_td_thr_getgregs_ID     = 0;
       
   113 
       
   114 // reg index fields
       
   115 static jfieldID pcRegIndex_ID            = 0;
       
   116 static jfieldID fpRegIndex_ID            = 0;
       
   117 
       
   118 // part of the class sharing workaround
       
   119 static jfieldID classes_jsa_fd_ID        = 0;
       
   120 static jfieldID p_file_map_header_ID     = 0;
       
   121 
       
   122 // method ids
       
   123 
       
   124 static jmethodID getThreadForThreadId_ID = 0;
       
   125 static jmethodID createSenderFrame_ID    = 0;
       
   126 static jmethodID createLoadObject_ID     = 0;
       
   127 static jmethodID createClosestSymbol_ID  = 0;
       
   128 static jmethodID listAdd_ID              = 0;
       
   129 
       
   130 /*
       
   131  * Functions we need from libthread_db
       
   132  */
       
   133 typedef td_err_e
       
   134         (*p_td_init_t)(void);
       
   135 typedef td_err_e
       
   136         (*p_td_ta_new_t)(void *, td_thragent_t **);
       
   137 typedef td_err_e
       
   138         (*p_td_ta_delete_t)(td_thragent_t *);
       
   139 typedef td_err_e
       
   140         (*p_td_ta_thr_iter_t)(const td_thragent_t *, td_thr_iter_f *, void *,
       
   141                 td_thr_state_e, int, sigset_t *, unsigned);
       
   142 typedef td_err_e
       
   143         (*p_td_thr_get_info_t)(const td_thrhandle_t *, td_thrinfo_t *);
       
   144 typedef td_err_e
       
   145         (*p_td_ta_map_id2thr_t)(const td_thragent_t *, thread_t,  td_thrhandle_t *);
       
   146 typedef td_err_e
       
   147         (*p_td_thr_getgregs_t)(const td_thrhandle_t *, prgregset_t);
       
   148 
       
   149 static void
       
   150 clear_libthread_db_ptrs(JNIEnv* env, jobject this_obj) {
       
   151   // release libthread_db agent, if we had created
       
   152   p_td_ta_delete_t p_td_ta_delete = 0;
       
   153   p_td_ta_delete = (p_td_ta_delete_t) env->GetLongField(this_obj, p_td_ta_delete_ID);
       
   154 
       
   155   td_thragent_t *p_td_thragent_t = 0;
       
   156   p_td_thragent_t = (td_thragent_t*) env->GetLongField(this_obj, p_td_thragent_t_ID);
       
   157   if (p_td_thragent_t != 0 && p_td_ta_delete != 0) {
       
   158      p_td_ta_delete(p_td_thragent_t);
       
   159   }
       
   160 
       
   161   // dlclose libthread_db.so
       
   162   void* libthread_db_handle = (void*) env->GetLongField(this_obj, libthread_db_handle_ID);
       
   163   if (libthread_db_handle != 0) {
       
   164     dlclose(libthread_db_handle);
       
   165   }
       
   166 
       
   167   env->SetLongField(this_obj, libthread_db_handle_ID, (jlong)0);
       
   168   env->SetLongField(this_obj, p_td_init_ID, (jlong)0);
       
   169   env->SetLongField(this_obj, p_td_ta_new_ID, (jlong)0);
       
   170   env->SetLongField(this_obj, p_td_ta_delete_ID, (jlong)0);
       
   171   env->SetLongField(this_obj, p_td_ta_thr_iter_ID, (jlong)0);
       
   172   env->SetLongField(this_obj, p_td_thr_get_info_ID, (jlong)0);
       
   173   env->SetLongField(this_obj, p_td_ta_map_id2thr_ID, (jlong)0);
       
   174   env->SetLongField(this_obj, p_td_thr_getgregs_ID, (jlong)0);
       
   175 }
       
   176 
       
   177 
       
   178 static void detach_internal(JNIEnv* env, jobject this_obj) {
       
   179   // clear libthread_db stuff
       
   180   clear_libthread_db_ptrs(env, this_obj);
       
   181 
       
   182   // release ptr to ps_prochandle
       
   183   jlong p_ps_prochandle;
       
   184   p_ps_prochandle = env->GetLongField(this_obj, p_ps_prochandle_ID);
       
   185   if (p_ps_prochandle != 0L) {
       
   186     Prelease((struct ps_prochandle*) p_ps_prochandle, PRELEASE_CLEAR);
       
   187   }
       
   188 
       
   189   // part of the class sharing workaround
       
   190   int classes_jsa_fd = env->GetIntField(this_obj, classes_jsa_fd_ID);
       
   191   if (classes_jsa_fd != -1) {
       
   192     close(classes_jsa_fd);
       
   193     struct FileMapHeader* pheader = (struct FileMapHeader*) env->GetLongField(this_obj, p_file_map_header_ID);
       
   194     if (pheader != NULL) {
       
   195       free(pheader);
       
   196     }
       
   197   }
       
   198 }
       
   199 
       
   200 // Is it okay to ignore libthread_db failure? Set env var to ignore
       
   201 // libthread_db failure. You can still debug, but will miss threads
       
   202 // related functionality.
       
   203 static bool sa_ignore_threaddb = (getenv("SA_IGNORE_THREADDB") != 0);
       
   204 
       
   205 #define HANDLE_THREADDB_FAILURE(msg)          \
       
   206   if (sa_ignore_threaddb) {                   \
       
   207      printf("libsaproc WARNING: %s\n", msg);  \
       
   208      return;                                  \
       
   209   } else {                                    \
       
   210      THROW_NEW_DEBUGGER_EXCEPTION(msg);       \
       
   211   }
       
   212 
       
   213 #define HANDLE_THREADDB_FAILURE_(msg, ret)    \
       
   214   if (sa_ignore_threaddb) {                   \
       
   215      printf("libsaproc WARNING: %s\n", msg);  \
       
   216      return ret;                              \
       
   217   } else {                                    \
       
   218      THROW_NEW_DEBUGGER_EXCEPTION_(msg, ret); \
       
   219   }
       
   220 
       
   221 static const char * alt_root = NULL;
       
   222 static int alt_root_len = -1;
       
   223 
       
   224 #define SA_ALTROOT "SA_ALTROOT"
       
   225 
       
   226 static void init_alt_root() {
       
   227   if (alt_root_len == -1) {
       
   228     alt_root = getenv(SA_ALTROOT);
       
   229     if (alt_root)
       
   230       alt_root_len = strlen(alt_root);
       
   231     else
       
   232       alt_root_len = 0;
       
   233   }
       
   234 }
       
   235 
       
   236 // This function is a complete substitute for the open system call
       
   237 // since it's also used to override open calls from libproc to
       
   238 // implement as a pathmap style facility for the SA.  If libproc
       
   239 // starts using other interfaces then this might have to extended to
       
   240 // cover other calls.
       
   241 extern "C" int libsaproc_open(const char * name, int oflag, ...) {
       
   242   if (oflag == O_RDONLY) {
       
   243     init_alt_root();
       
   244 
       
   245     if (_libsaproc_debug) {
       
   246       printf("libsaproc DEBUG: libsaproc_open %s\n", name);
       
   247     }
       
   248 
       
   249     if (alt_root_len > 0) {
       
   250       int fd = -1;
       
   251       char alt_path[PATH_MAX+1];
       
   252 
       
   253       strcpy(alt_path, alt_root);
       
   254       strcat(alt_path, name);
       
   255       fd = open(alt_path, O_RDONLY);
       
   256       if (fd >= 0) {
       
   257         if (_libsaproc_debug) {
       
   258           printf("libsaproc DEBUG: libsaproc_open substituted %s\n", alt_path);
       
   259         }
       
   260         return fd;
       
   261       }
       
   262 
       
   263       if (strrchr(name, '/')) {
       
   264         strcpy(alt_path, alt_root);
       
   265         strcat(alt_path, strrchr(name, '/'));
       
   266         fd = open(alt_path, O_RDONLY);
       
   267         if (fd >= 0) {
       
   268           if (_libsaproc_debug) {
       
   269             printf("libsaproc DEBUG: libsaproc_open substituted %s\n", alt_path);
       
   270           }
       
   271           return fd;
       
   272         }
       
   273       }
       
   274     }
       
   275   }
       
   276 
       
   277   {
       
   278     mode_t mode;
       
   279     va_list ap;
       
   280     va_start(ap, oflag);
       
   281     mode = va_arg(ap, mode_t);
       
   282     va_end(ap);
       
   283 
       
   284     return open(name, oflag, mode);
       
   285   }
       
   286 }
       
   287 
       
   288 
       
   289 static void * pathmap_dlopen(const char * name, int mode) {
       
   290   init_alt_root();
       
   291 
       
   292   if (_libsaproc_debug) {
       
   293     printf("libsaproc DEBUG: pathmap_dlopen %s\n", name);
       
   294   }
       
   295 
       
   296   void * handle = NULL;
       
   297   if (alt_root_len > 0) {
       
   298     char alt_path[PATH_MAX+1];
       
   299     strcpy(alt_path, alt_root);
       
   300     strcat(alt_path, name);
       
   301     handle = dlopen(alt_path, mode);
       
   302     if (_libsaproc_debug && handle) {
       
   303       printf("libsaproc DEBUG: pathmap_dlopen substituted %s\n", alt_path);
       
   304     }
       
   305 
       
   306     if (handle == NULL && strrchr(name, '/')) {
       
   307       strcpy(alt_path, alt_root);
       
   308       strcat(alt_path, strrchr(name, '/'));
       
   309       handle = dlopen(alt_path, mode);
       
   310       if (_libsaproc_debug && handle) {
       
   311         printf("libsaproc DEBUG: pathmap_dlopen substituted %s\n", alt_path);
       
   312       }
       
   313     }
       
   314   }
       
   315   if (handle == NULL) {
       
   316     handle = dlopen(name, mode);
       
   317   }
       
   318   if (_libsaproc_debug) {
       
   319     printf("libsaproc DEBUG: pathmap_dlopen %s return 0x%lx\n", name, (unsigned long) handle);
       
   320   }
       
   321   return handle;
       
   322 }
       
   323 
       
   324 // libproc and libthread_db callback functions
       
   325 
       
   326 extern "C" {
       
   327 
       
   328 static int
       
   329 init_libthread_db_ptrs(void *cd, const prmap_t *pmp, const char *object_name) {
       
   330   Debugger* dbg = (Debugger*) cd;
       
   331   JNIEnv* env = dbg->env;
       
   332   jobject this_obj = dbg->this_obj;
       
   333   struct ps_prochandle* ph = (struct ps_prochandle*) env->GetLongField(this_obj, p_ps_prochandle_ID);
       
   334 
       
   335   char *s1 = 0, *s2 = 0;
       
   336   char libthread_db[PATH_MAX];
       
   337 
       
   338   if (strstr(object_name, "/libthread.so.") == NULL)
       
   339      return (0);
       
   340 
       
   341   /*
       
   342    * We found a libthread.
       
   343    * dlopen() the matching libthread_db and get the thread agent handle.
       
   344    */
       
   345   if (Pstatus(ph)->pr_dmodel == PR_MODEL_NATIVE) {
       
   346      (void) strcpy(libthread_db, object_name);
       
   347      s1 = (char*) strstr(object_name, ".so.");
       
   348      s2 = (char*) strstr(libthread_db, ".so.");
       
   349      (void) strcpy(s2, "_db");
       
   350      s2 += 3;
       
   351      (void) strcpy(s2, s1);
       
   352   } else {
       
   353 #ifdef _LP64
       
   354      /*
       
   355       * The victim process is 32-bit, we are 64-bit.
       
   356       * We have to find the 64-bit version of libthread_db
       
   357       * that matches the victim's 32-bit version of libthread.
       
   358       */
       
   359      (void) strcpy(libthread_db, object_name);
       
   360      s1 = (char*) strstr(object_name, "/libthread.so.");
       
   361      s2 = (char*) strstr(libthread_db, "/libthread.so.");
       
   362      (void) strcpy(s2, "/64");
       
   363      s2 += 3;
       
   364      (void) strcpy(s2, s1);
       
   365      s1 = (char*) strstr(s1, ".so.");
       
   366      s2 = (char*) strstr(s2, ".so.");
       
   367      (void) strcpy(s2, "_db");
       
   368      s2 += 3;
       
   369      (void) strcpy(s2, s1);
       
   370 #else
       
   371      return (0);
       
   372 #endif  /* _LP64 */
       
   373   }
       
   374 
       
   375   void* libthread_db_handle = 0;
       
   376   if ((libthread_db_handle = pathmap_dlopen(libthread_db, RTLD_LAZY|RTLD_LOCAL)) == NULL) {
       
   377      char errMsg[PATH_MAX + 256];
       
   378      sprintf(errMsg, "Can't load %s!", libthread_db);
       
   379      HANDLE_THREADDB_FAILURE_(errMsg, 0);
       
   380   }
       
   381   env->SetLongField(this_obj, libthread_db_handle_ID, (jlong)(uintptr_t)libthread_db_handle);
       
   382 
       
   383   void* tmpPtr = 0;
       
   384   tmpPtr = dlsym(libthread_db_handle, "td_init");
       
   385   if (tmpPtr == 0) {
       
   386      HANDLE_THREADDB_FAILURE_("dlsym failed on td_init!", 0);
       
   387   }
       
   388   env->SetLongField(this_obj, p_td_init_ID, (jlong)(uintptr_t) tmpPtr);
       
   389 
       
   390   tmpPtr =dlsym(libthread_db_handle, "td_ta_new");
       
   391   if (tmpPtr == 0) {
       
   392      HANDLE_THREADDB_FAILURE_("dlsym failed on td_ta_new!", 0);
       
   393   }
       
   394   env->SetLongField(this_obj, p_td_ta_new_ID, (jlong)(uintptr_t) tmpPtr);
       
   395 
       
   396   tmpPtr = dlsym(libthread_db_handle, "td_ta_delete");
       
   397   if (tmpPtr == 0) {
       
   398      HANDLE_THREADDB_FAILURE_("dlsym failed on td_ta_delete!", 0);
       
   399   }
       
   400   env->SetLongField(this_obj, p_td_ta_delete_ID, (jlong)(uintptr_t) tmpPtr);
       
   401 
       
   402   tmpPtr = dlsym(libthread_db_handle, "td_ta_thr_iter");
       
   403   if (tmpPtr == 0) {
       
   404      HANDLE_THREADDB_FAILURE_("dlsym failed on td_ta_thr_iter!", 0);
       
   405   }
       
   406   env->SetLongField(this_obj, p_td_ta_thr_iter_ID, (jlong)(uintptr_t) tmpPtr);
       
   407 
       
   408   tmpPtr = dlsym(libthread_db_handle, "td_thr_get_info");
       
   409   if (tmpPtr == 0) {
       
   410      HANDLE_THREADDB_FAILURE_("dlsym failed on td_thr_get_info!", 0);
       
   411   }
       
   412   env->SetLongField(this_obj, p_td_thr_get_info_ID, (jlong)(uintptr_t) tmpPtr);
       
   413 
       
   414   tmpPtr = dlsym(libthread_db_handle, "td_ta_map_id2thr");
       
   415   if (tmpPtr == 0) {
       
   416      HANDLE_THREADDB_FAILURE_("dlsym failed on td_ta_map_id2thr!", 0);
       
   417   }
       
   418   env->SetLongField(this_obj, p_td_ta_map_id2thr_ID, (jlong)(uintptr_t) tmpPtr);
       
   419 
       
   420   tmpPtr = dlsym(libthread_db_handle, "td_thr_getgregs");
       
   421   if (tmpPtr == 0) {
       
   422      HANDLE_THREADDB_FAILURE_("dlsym failed on td_thr_getgregs!", 0);
       
   423   }
       
   424   env->SetLongField(this_obj, p_td_thr_getgregs_ID, (jlong)(uintptr_t) tmpPtr);
       
   425 
       
   426   return 1;
       
   427 }
       
   428 
       
   429 static int
       
   430 fill_thread_list(const td_thrhandle_t *p_td_thragent_t, void* cd) {
       
   431   DebuggerWithObject* dbgo = (DebuggerWithObject*) cd;
       
   432   JNIEnv* env = dbgo->env;
       
   433   jobject this_obj = dbgo->this_obj;
       
   434   jobject list = dbgo->obj;
       
   435 
       
   436   td_thrinfo_t thrinfo;
       
   437   p_td_thr_get_info_t p_td_thr_get_info = (p_td_thr_get_info_t) env->GetLongField(this_obj, p_td_thr_get_info_ID);
       
   438 
       
   439   if (p_td_thr_get_info(p_td_thragent_t, &thrinfo) != TD_OK)
       
   440     return (0);
       
   441 
       
   442   jobject threadProxy = env->CallObjectMethod(this_obj, getThreadForThreadId_ID, (jlong)(uintptr_t) thrinfo.ti_tid);
       
   443   CHECK_EXCEPTION_(1);
       
   444   env->CallBooleanMethod(list, listAdd_ID, threadProxy);
       
   445   CHECK_EXCEPTION_(1);
       
   446   return 0;
       
   447 }
       
   448 
       
   449 static int
       
   450 fill_load_object_list(void *cd, const prmap_t* pmp, const char* obj_name) {
       
   451 
       
   452   if (obj_name) {
       
   453      DebuggerWithObject* dbgo = (DebuggerWithObject*) cd;
       
   454      JNIEnv* env = dbgo->env;
       
   455      jobject this_obj = dbgo->this_obj;
       
   456      jobject list = dbgo->obj;
       
   457 
       
   458      jstring objectName = env->NewStringUTF(obj_name);
       
   459      CHECK_EXCEPTION_(1);
       
   460 
       
   461      jlong mapSize = (jlong) pmp->pr_size;
       
   462      jobject sharedObject = env->CallObjectMethod(this_obj, createLoadObject_ID,
       
   463                                   objectName, mapSize, (jlong)(uintptr_t)pmp->pr_vaddr);
       
   464      CHECK_EXCEPTION_(1);
       
   465      env->CallBooleanMethod(list, listAdd_ID, sharedObject);
       
   466      CHECK_EXCEPTION_(1);
       
   467   }
       
   468 
       
   469   return 0;
       
   470 }
       
   471 
       
   472 // Pstack_iter() proc_stack_f callback prior to Nevada-B159
       
   473 static int
       
   474 fill_cframe_list(void *cd, const prgregset_t regs, uint_t argc, const long *argv) {
       
   475   DebuggerWith2Objects* dbgo2 = (DebuggerWith2Objects*) cd;
       
   476   JNIEnv* env = dbgo2->env;
       
   477   jobject this_obj = dbgo2->this_obj;
       
   478   jobject curFrame = dbgo2->obj2;
       
   479 
       
   480   jint pcRegIndex = env->GetIntField(this_obj, pcRegIndex_ID);
       
   481   jint fpRegIndex = env->GetIntField(this_obj, fpRegIndex_ID);
       
   482 
       
   483   jlong pc = (jlong) (uintptr_t) regs[pcRegIndex];
       
   484   jlong fp = (jlong) (uintptr_t) regs[fpRegIndex];
       
   485 
       
   486   dbgo2->obj2 = env->CallObjectMethod(this_obj, createSenderFrame_ID,
       
   487                                     curFrame, pc, fp);
       
   488   CHECK_EXCEPTION_(1);
       
   489   if (dbgo2->obj == 0) {
       
   490      dbgo2->obj = dbgo2->obj2;
       
   491   }
       
   492   return 0;
       
   493 }
       
   494 
       
   495 // Pstack_iter() proc_stack_f callback in Nevada-B159 or later
       
   496 /*ARGSUSED*/
       
   497 static int
       
   498 wrapper_fill_cframe_list(void *cd, const prgregset_t regs, uint_t argc,
       
   499                          const long *argv, int frame_flags, int sig) {
       
   500   return(fill_cframe_list(cd, regs, argc, argv));
       
   501 }
       
   502 
       
   503 // part of the class sharing workaround
       
   504 
       
   505 // FIXME: !!HACK ALERT!!
       
   506 
       
   507 // The format of sharing achive file header is needed to read shared heap
       
   508 // file mappings. For now, I am hard coding portion of FileMapHeader here.
       
   509 // Refer to filemap.hpp.
       
   510 
       
   511 // FileMapHeader describes the shared space data in the file to be
       
   512 // mapped.  This structure gets written to a file.  It is not a class, so
       
   513 // that the compilers don't add any compiler-private data to it.
       
   514 
       
   515 const int NUM_SHARED_MAPS = 4;
       
   516 
       
   517 // Refer to FileMapInfo::_current_version in filemap.hpp
       
   518 const int CURRENT_ARCHIVE_VERSION = 1;
       
   519 
       
   520 struct FileMapHeader {
       
   521  int   _magic;              // identify file type.
       
   522  int   _version;            // (from enum, above.)
       
   523  size_t _alignment;         // how shared archive should be aligned
       
   524 
       
   525 
       
   526  struct space_info {
       
   527    int    _file_offset;     // sizeof(this) rounded to vm page size
       
   528    char*  _base;            // copy-on-write base address
       
   529    size_t _capacity;        // for validity checking
       
   530    size_t _used;            // for setting space top on read
       
   531 
       
   532    bool   _read_only;       // read only space?
       
   533    bool   _allow_exec;      // executable code in space?
       
   534 
       
   535  } _space[NUM_SHARED_MAPS];
       
   536 
       
   537  // Ignore the rest of the FileMapHeader. We don't need those fields here.
       
   538 };
       
   539 
       
   540 static bool
       
   541 read_jboolean(struct ps_prochandle* ph, psaddr_t addr, jboolean* pvalue) {
       
   542   jboolean i;
       
   543   if (ps_pread(ph, addr, &i, sizeof(i)) == PS_OK) {
       
   544     *pvalue = i;
       
   545     return true;
       
   546   } else {
       
   547     return false;
       
   548   }
       
   549 }
       
   550 
       
   551 static bool
       
   552 read_pointer(struct ps_prochandle* ph, psaddr_t addr, uintptr_t* pvalue) {
       
   553   uintptr_t uip;
       
   554   if (ps_pread(ph, addr, &uip, sizeof(uip)) == PS_OK) {
       
   555     *pvalue = uip;
       
   556     return true;
       
   557   } else {
       
   558     return false;
       
   559   }
       
   560 }
       
   561 
       
   562 static bool
       
   563 read_string(struct ps_prochandle* ph, psaddr_t addr, char* buf, size_t size) {
       
   564   char ch = ' ';
       
   565   size_t i = 0;
       
   566 
       
   567   while (ch != '\0') {
       
   568     if (ps_pread(ph, addr, &ch, sizeof(ch)) != PS_OK)
       
   569       return false;
       
   570 
       
   571     if (i < size - 1) {
       
   572       buf[i] = ch;
       
   573     } else { // smaller buffer
       
   574       return false;
       
   575     }
       
   576 
       
   577     i++; addr++;
       
   578   }
       
   579 
       
   580   buf[i] = '\0';
       
   581   return true;
       
   582 }
       
   583 
       
   584 #define USE_SHARED_SPACES_SYM   "UseSharedSpaces"
       
   585 // mangled symbol name for Arguments::SharedArchivePath
       
   586 #define SHARED_ARCHIVE_PATH_SYM "__1cJArgumentsRSharedArchivePath_"
       
   587 
       
   588 static int
       
   589 init_classsharing_workaround(void *cd, const prmap_t* pmap, const char* obj_name) {
       
   590   Debugger* dbg = (Debugger*) cd;
       
   591   JNIEnv*   env = dbg->env;
       
   592   jobject this_obj = dbg->this_obj;
       
   593   const char* jvm_name = 0;
       
   594   if ((jvm_name = strstr(obj_name, "libjvm.so")) != NULL) {
       
   595     jvm_name = obj_name;
       
   596   } else {
       
   597     return 0;
       
   598   }
       
   599 
       
   600   struct ps_prochandle* ph = (struct ps_prochandle*) env->GetLongField(this_obj, p_ps_prochandle_ID);
       
   601 
       
   602   // initialize classes.jsa file descriptor field.
       
   603   dbg->env->SetIntField(this_obj, classes_jsa_fd_ID, -1);
       
   604 
       
   605   // check whether class sharing is on by reading variable "UseSharedSpaces"
       
   606   psaddr_t useSharedSpacesAddr = 0;
       
   607   ps_pglobal_lookup(ph, jvm_name, USE_SHARED_SPACES_SYM, &useSharedSpacesAddr);
       
   608   if (useSharedSpacesAddr == 0) {
       
   609     THROW_NEW_DEBUGGER_EXCEPTION_("can't find 'UseSharedSpaces' flag\n", 1);
       
   610   }
       
   611 
       
   612   // read the value of the flag "UseSharedSpaces"
       
   613   // Since hotspot types are not available to build this library. So
       
   614   // equivalent type "jboolean" is used to read the value of "UseSharedSpaces"
       
   615   // which is same as hotspot type "bool".
       
   616   jboolean value = 0;
       
   617   if (read_jboolean(ph, useSharedSpacesAddr, &value) != true) {
       
   618     THROW_NEW_DEBUGGER_EXCEPTION_("can't read 'UseSharedSpaces' flag", 1);
       
   619   } else if ((int)value == 0) {
       
   620     print_debug("UseSharedSpaces is false, assuming -Xshare:off!\n");
       
   621     return 1;
       
   622   }
       
   623 
       
   624   char classes_jsa[PATH_MAX];
       
   625   psaddr_t sharedArchivePathAddrAddr = 0;
       
   626   ps_pglobal_lookup(ph, jvm_name, SHARED_ARCHIVE_PATH_SYM, &sharedArchivePathAddrAddr);
       
   627   if (sharedArchivePathAddrAddr == 0) {
       
   628     print_debug("can't find symbol 'Arguments::SharedArchivePath'\n");
       
   629     THROW_NEW_DEBUGGER_EXCEPTION_("can't get shared archive path from debuggee", 1);
       
   630   }
       
   631 
       
   632   uintptr_t sharedArchivePathAddr = 0;
       
   633   if (read_pointer(ph, sharedArchivePathAddrAddr, &sharedArchivePathAddr) != true) {
       
   634     print_debug("can't find read pointer 'Arguments::SharedArchivePath'\n");
       
   635     THROW_NEW_DEBUGGER_EXCEPTION_("can't get shared archive path from debuggee", 1);
       
   636   }
       
   637 
       
   638   if (read_string(ph, (psaddr_t)sharedArchivePathAddr, classes_jsa, sizeof(classes_jsa)) != true) {
       
   639     print_debug("can't find read 'Arguments::SharedArchivePath' value\n");
       
   640     THROW_NEW_DEBUGGER_EXCEPTION_("can't get shared archive path from debuggee", 1);
       
   641   }
       
   642 
       
   643   print_debug("looking for %s\n", classes_jsa);
       
   644 
       
   645   // open the classes.jsa
       
   646   int fd = libsaproc_open(classes_jsa, O_RDONLY);
       
   647   if (fd < 0) {
       
   648     char errMsg[ERR_MSG_SIZE];
       
   649     sprintf(errMsg, "can't open shared archive file %s", classes_jsa);
       
   650     THROW_NEW_DEBUGGER_EXCEPTION_(errMsg, 1);
       
   651   } else {
       
   652     print_debug("opened shared archive file %s\n", classes_jsa);
       
   653   }
       
   654 
       
   655   // parse classes.jsa
       
   656   struct FileMapHeader* pheader = (struct FileMapHeader*) malloc(sizeof(struct FileMapHeader));
       
   657   if (pheader == NULL) {
       
   658     close(fd);
       
   659     THROW_NEW_DEBUGGER_EXCEPTION_("can't allocate memory for shared file map header", 1);
       
   660   }
       
   661 
       
   662   memset(pheader, 0, sizeof(struct FileMapHeader));
       
   663   // read FileMapHeader
       
   664   size_t n = read(fd, pheader, sizeof(struct FileMapHeader));
       
   665   if (n != sizeof(struct FileMapHeader)) {
       
   666     char errMsg[ERR_MSG_SIZE];
       
   667     sprintf(errMsg, "unable to read shared archive file map header from %s", classes_jsa);
       
   668     close(fd);
       
   669     free(pheader);
       
   670     THROW_NEW_DEBUGGER_EXCEPTION_(errMsg, 1);
       
   671   }
       
   672 
       
   673   // check file magic
       
   674   if (pheader->_magic != 0xf00baba2) {
       
   675     char errMsg[ERR_MSG_SIZE];
       
   676     sprintf(errMsg, "%s has bad shared archive magic 0x%x, expecting 0xf00baba2",
       
   677                    classes_jsa, pheader->_magic);
       
   678     close(fd);
       
   679     free(pheader);
       
   680     THROW_NEW_DEBUGGER_EXCEPTION_(errMsg, 1);
       
   681   }
       
   682 
       
   683   // check version
       
   684   if (pheader->_version != CURRENT_ARCHIVE_VERSION) {
       
   685     char errMsg[ERR_MSG_SIZE];
       
   686     sprintf(errMsg, "%s has wrong shared archive version %d, expecting %d",
       
   687                    classes_jsa, pheader->_version, CURRENT_ARCHIVE_VERSION);
       
   688     close(fd);
       
   689     free(pheader);
       
   690     THROW_NEW_DEBUGGER_EXCEPTION_(errMsg, 1);
       
   691   }
       
   692 
       
   693   if (_libsaproc_debug) {
       
   694     for (int m = 0; m < NUM_SHARED_MAPS; m++) {
       
   695        print_debug("shared file offset %d mapped at 0x%lx, size = %ld, read only? = %d\n",
       
   696           pheader->_space[m]._file_offset, pheader->_space[m]._base,
       
   697           pheader->_space[m]._used, pheader->_space[m]._read_only);
       
   698     }
       
   699   }
       
   700 
       
   701   // FIXME: For now, omitting other checks such as VM version etc.
       
   702 
       
   703   // store class archive file fd and map header in debugger object fields
       
   704   dbg->env->SetIntField(this_obj, classes_jsa_fd_ID, fd);
       
   705   dbg->env->SetLongField(this_obj, p_file_map_header_ID, (jlong)(uintptr_t) pheader);
       
   706   return 1;
       
   707 }
       
   708 
       
   709 } // extern "C"
       
   710 
       
   711 // error messages for proc_arg_grab failure codes. The messages are
       
   712 // modified versions of comments against corresponding #defines in
       
   713 // libproc.h.
       
   714 static const char* proc_arg_grab_errmsgs[] = {
       
   715                       "",
       
   716  /* G_NOPROC */       "No such process",
       
   717  /* G_NOCORE */       "No such core file",
       
   718  /* G_NOPROCORCORE */ "No such process or core",
       
   719  /* G_NOEXEC */       "Cannot locate executable file",
       
   720  /* G_ZOMB   */       "Zombie processs",
       
   721  /* G_PERM   */       "No permission to attach",
       
   722  /* G_BUSY   */       "Another process has already attached",
       
   723  /* G_SYS    */       "System process - can not attach",
       
   724  /* G_SELF   */       "Process is self - can't debug myself!",
       
   725  /* G_INTR   */       "Interrupt received while grabbing",
       
   726  /* G_LP64   */       "debuggee is 64 bit, use java -d64 for debugger",
       
   727  /* G_FORMAT */       "File is not an ELF format core file - corrupted core?",
       
   728  /* G_ELF    */       "Libelf error while parsing an ELF file",
       
   729  /* G_NOTE   */       "Required PT_NOTE Phdr not present - corrupted core?",
       
   730 };
       
   731 
       
   732 static void attach_internal(JNIEnv* env, jobject this_obj, jstring cmdLine, jboolean isProcess) {
       
   733   jboolean isCopy;
       
   734   int gcode;
       
   735   const char* cmdLine_cstr = env->GetStringUTFChars(cmdLine, &isCopy);
       
   736   CHECK_EXCEPTION;
       
   737 
       
   738   // some older versions of libproc.so crash when trying to attach 32 bit
       
   739   // debugger to 64 bit core file. check and throw error.
       
   740 #ifndef _LP64
       
   741   atoi(cmdLine_cstr);
       
   742   if (errno) {
       
   743      // core file
       
   744      int core_fd;
       
   745      if ((core_fd = open64(cmdLine_cstr, O_RDONLY)) >= 0) {
       
   746         Elf32_Ehdr e32;
       
   747         if (pread64(core_fd, &e32, sizeof (e32), 0) == sizeof (e32) &&
       
   748             memcmp(&e32.e_ident[EI_MAG0], ELFMAG, SELFMAG) == 0 &&
       
   749             e32.e_type == ET_CORE && e32.e_ident[EI_CLASS] == ELFCLASS64) {
       
   750               close(core_fd);
       
   751               THROW_NEW_DEBUGGER_EXCEPTION("debuggee is 64 bit, use java -d64 for debugger");
       
   752         }
       
   753         close(core_fd);
       
   754      }
       
   755      // all other conditions are handled by libproc.so.
       
   756   }
       
   757 #endif
       
   758 
       
   759   // connect to process/core
       
   760   struct ps_prochandle* ph = proc_arg_grab(cmdLine_cstr, (isProcess? PR_ARG_PIDS : PR_ARG_CORES), PGRAB_FORCE, &gcode);
       
   761   env->ReleaseStringUTFChars(cmdLine, cmdLine_cstr);
       
   762   if (! ph) {
       
   763      if (gcode > 0 && gcode < sizeof(proc_arg_grab_errmsgs)/sizeof(const char*)) {
       
   764         char errMsg[ERR_MSG_SIZE];
       
   765         sprintf(errMsg, "Attach failed : %s", proc_arg_grab_errmsgs[gcode]);
       
   766         THROW_NEW_DEBUGGER_EXCEPTION(errMsg);
       
   767     } else {
       
   768         if (_libsaproc_debug && gcode == G_STRANGE) {
       
   769            perror("libsaproc DEBUG: ");
       
   770         }
       
   771         if (isProcess) {
       
   772            THROW_NEW_DEBUGGER_EXCEPTION("Not able to attach to process!");
       
   773         } else {
       
   774            THROW_NEW_DEBUGGER_EXCEPTION("Not able to attach to core file!");
       
   775         }
       
   776      }
       
   777   }
       
   778 
       
   779   // even though libproc.so supports 64 bit debugger and 32 bit debuggee, we don't
       
   780   // support such cross-bit-debugging. check for that combination and throw error.
       
   781 #ifdef _LP64
       
   782   int data_model;
       
   783   if (ps_pdmodel(ph, &data_model) != PS_OK) {
       
   784      Prelease(ph, PRELEASE_CLEAR);
       
   785      THROW_NEW_DEBUGGER_EXCEPTION("can't determine debuggee data model (ILP32? or LP64?)");
       
   786   }
       
   787   if (data_model == PR_MODEL_ILP32) {
       
   788      Prelease(ph, PRELEASE_CLEAR);
       
   789      THROW_NEW_DEBUGGER_EXCEPTION("debuggee is 32 bit, use 32 bit java for debugger");
       
   790   }
       
   791 #endif
       
   792 
       
   793   env->SetLongField(this_obj, p_ps_prochandle_ID, (jlong)(uintptr_t)ph);
       
   794 
       
   795   Debugger dbg;
       
   796   dbg.env = env;
       
   797   dbg.this_obj = this_obj;
       
   798   jthrowable exception = 0;
       
   799   if (! isProcess) {
       
   800     /*
       
   801      * With class sharing, shared perm. gen heap is allocated in with MAP_SHARED|PROT_READ.
       
   802      * These pages are mapped from the file "classes.jsa". MAP_SHARED pages are not dumped
       
   803      * in Solaris core.To read shared heap pages, we have to read classes.jsa file.
       
   804      */
       
   805     Pobject_iter(ph, init_classsharing_workaround, &dbg);
       
   806     exception = env->ExceptionOccurred();
       
   807     if (exception) {
       
   808       env->ExceptionClear();
       
   809       detach_internal(env, this_obj);
       
   810       env->Throw(exception);
       
   811       return;
       
   812     }
       
   813   }
       
   814 
       
   815   /*
       
   816    * Iterate over the process mappings looking
       
   817    * for libthread and then dlopen the appropriate
       
   818    * libthread_db and get function pointers.
       
   819    */
       
   820   Pobject_iter(ph, init_libthread_db_ptrs, &dbg);
       
   821   exception = env->ExceptionOccurred();
       
   822   if (exception) {
       
   823     env->ExceptionClear();
       
   824     if (!sa_ignore_threaddb) {
       
   825       detach_internal(env, this_obj);
       
   826       env->Throw(exception);
       
   827     }
       
   828     return;
       
   829   }
       
   830 
       
   831   // init libthread_db and create thread_db agent
       
   832   p_td_init_t p_td_init = (p_td_init_t) env->GetLongField(this_obj, p_td_init_ID);
       
   833   if (p_td_init == 0) {
       
   834     if (!sa_ignore_threaddb) {
       
   835       detach_internal(env, this_obj);
       
   836     }
       
   837     HANDLE_THREADDB_FAILURE("Did not find libthread in target process/core!");
       
   838   }
       
   839 
       
   840   if (p_td_init() != TD_OK) {
       
   841     if (!sa_ignore_threaddb) {
       
   842       detach_internal(env, this_obj);
       
   843     }
       
   844     HANDLE_THREADDB_FAILURE("Can't initialize thread_db!");
       
   845   }
       
   846 
       
   847   p_td_ta_new_t p_td_ta_new = (p_td_ta_new_t) env->GetLongField(this_obj, p_td_ta_new_ID);
       
   848 
       
   849   td_thragent_t *p_td_thragent_t = 0;
       
   850   if (p_td_ta_new(ph, &p_td_thragent_t) != TD_OK) {
       
   851     if (!sa_ignore_threaddb) {
       
   852       detach_internal(env, this_obj);
       
   853     }
       
   854     HANDLE_THREADDB_FAILURE("Can't create thread_db agent!");
       
   855   }
       
   856   env->SetLongField(this_obj, p_td_thragent_t_ID, (jlong)(uintptr_t) p_td_thragent_t);
       
   857 
       
   858 }
       
   859 
       
   860 /*
       
   861  * Class:     sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal
       
   862  * Method:    attach0
       
   863  * Signature: (Ljava/lang/String;)V
       
   864  * Description: process detach
       
   865  */
       
   866 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal_attach0__Ljava_lang_String_2
       
   867   (JNIEnv *env, jobject this_obj, jstring pid) {
       
   868   attach_internal(env, this_obj, pid, JNI_TRUE);
       
   869 }
       
   870 
       
   871 /*
       
   872  * Class:     sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal
       
   873  * Method:    attach0
       
   874  * Signature: (Ljava/lang/String;Ljava/lang/String;)V
       
   875  * Description: core file detach
       
   876  */
       
   877 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal_attach0__Ljava_lang_String_2Ljava_lang_String_2
       
   878   (JNIEnv *env, jobject this_obj, jstring executable, jstring corefile) {
       
   879   // ignore executable file name, libproc.so can detect a.out name anyway.
       
   880   attach_internal(env, this_obj, corefile, JNI_FALSE);
       
   881 }
       
   882 
       
   883 
       
   884 /*
       
   885  * Class:       sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal
       
   886  * Method:      detach0
       
   887  * Signature:   ()V
       
   888  * Description: process/core file detach
       
   889  */
       
   890 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal_detach0
       
   891   (JNIEnv *env, jobject this_obj) {
       
   892   detach_internal(env, this_obj);
       
   893 }
       
   894 
       
   895 /*
       
   896  * Class:       sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal
       
   897  * Method:      getRemoteProcessAddressSize0
       
   898  * Signature:   ()I
       
   899  * Description: get process/core address size
       
   900  */
       
   901 JNIEXPORT jint JNICALL Java_sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal_getRemoteProcessAddressSize0
       
   902   (JNIEnv *env, jobject this_obj) {
       
   903   jlong p_ps_prochandle;
       
   904   p_ps_prochandle = env->GetLongField(this_obj, p_ps_prochandle_ID);
       
   905   int data_model = PR_MODEL_ILP32;
       
   906   ps_pdmodel((struct ps_prochandle*) p_ps_prochandle, &data_model);
       
   907   print_debug("debuggee is %d bit\n", data_model == PR_MODEL_ILP32? 32 : 64);
       
   908   return (jint) data_model == PR_MODEL_ILP32? 32 : 64;
       
   909 }
       
   910 
       
   911 /*
       
   912  * Class:       sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal
       
   913  * Method:      getPageSize0
       
   914  * Signature:   ()I
       
   915  * Description: get process/core page size
       
   916  */
       
   917 JNIEXPORT jint JNICALL Java_sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal_getPageSize0
       
   918   (JNIEnv *env, jobject this_obj) {
       
   919 
       
   920 /*
       
   921   We are not yet attached to a java process or core file. getPageSize is called from
       
   922   the constructor of ProcDebuggerLocal. The following won't work!
       
   923 
       
   924     jlong p_ps_prochandle;
       
   925     p_ps_prochandle = env->GetLongField(this_obj, p_ps_prochandle_ID);
       
   926     CHECK_EXCEPTION_(-1);
       
   927     struct ps_prochandle* prochandle = (struct ps_prochandle*) p_ps_prochandle;
       
   928     return (Pstate(prochandle) == PS_DEAD) ? Pgetauxval(prochandle, AT_PAGESZ)
       
   929                                            : getpagesize();
       
   930 
       
   931   So even though core may have been generated with a different page size settings, for now
       
   932   call getpagesize.
       
   933 */
       
   934 
       
   935   return getpagesize();
       
   936 }
       
   937 
       
   938 /*
       
   939  * Class:       sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal
       
   940  * Method:      getThreadIntegerRegisterSet0
       
   941  * Signature:   (J)[J
       
   942  * Description: get gregset for a given thread specified by thread id
       
   943  */
       
   944 JNIEXPORT jlongArray JNICALL Java_sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal_getThreadIntegerRegisterSet0
       
   945   (JNIEnv *env, jobject this_obj, jlong tid) {
       
   946   // map the thread id to thread handle
       
   947   p_td_ta_map_id2thr_t p_td_ta_map_id2thr = (p_td_ta_map_id2thr_t) env->GetLongField(this_obj, p_td_ta_map_id2thr_ID);
       
   948 
       
   949   td_thragent_t* p_td_thragent_t = (td_thragent_t*) env->GetLongField(this_obj, p_td_thragent_t_ID);
       
   950   if (p_td_thragent_t == 0) {
       
   951      return 0;
       
   952   }
       
   953 
       
   954   td_thrhandle_t thr_handle;
       
   955   if (p_td_ta_map_id2thr(p_td_thragent_t, (thread_t) tid, &thr_handle) != TD_OK) {
       
   956      THROW_NEW_DEBUGGER_EXCEPTION_("can't map thread id to thread handle!", 0);
       
   957   }
       
   958 
       
   959   p_td_thr_getgregs_t p_td_thr_getgregs = (p_td_thr_getgregs_t) env->GetLongField(this_obj, p_td_thr_getgregs_ID);
       
   960   prgregset_t gregs;
       
   961   p_td_thr_getgregs(&thr_handle, gregs);
       
   962 
       
   963   jlongArray res = env->NewLongArray(NPRGREG);
       
   964   CHECK_EXCEPTION_(0);
       
   965   jboolean isCopy;
       
   966   jlong* ptr = env->GetLongArrayElements(res, &isCopy);
       
   967   CHECK_EXCEPTION_(NULL);
       
   968   for (int i = 0; i < NPRGREG; i++) {
       
   969     ptr[i] = (jlong) (uintptr_t) gregs[i];
       
   970   }
       
   971   env->ReleaseLongArrayElements(res, ptr, JNI_COMMIT);
       
   972   return res;
       
   973 }
       
   974 
       
   975 /*
       
   976  * Class:       sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal
       
   977  * Method:      fillThreadList0
       
   978  * Signature:   (Ljava/util/List;)V
       
   979  * Description: fills thread list of the debuggee process/core
       
   980  */
       
   981 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal_fillThreadList0
       
   982   (JNIEnv *env, jobject this_obj, jobject list) {
       
   983 
       
   984   td_thragent_t* p_td_thragent_t = (td_thragent_t*) env->GetLongField(this_obj, p_td_thragent_t_ID);
       
   985   if (p_td_thragent_t == 0) {
       
   986      return;
       
   987   }
       
   988 
       
   989   p_td_ta_thr_iter_t p_td_ta_thr_iter = (p_td_ta_thr_iter_t) env->GetLongField(this_obj, p_td_ta_thr_iter_ID);
       
   990 
       
   991   DebuggerWithObject dbgo;
       
   992   dbgo.env = env;
       
   993   dbgo.this_obj = this_obj;
       
   994   dbgo.obj = list;
       
   995 
       
   996   p_td_ta_thr_iter(p_td_thragent_t, fill_thread_list, &dbgo,
       
   997                    TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY, TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS);
       
   998 }
       
   999 
       
  1000 #ifndef SOLARIS_11_B159_OR_LATER
       
  1001 // building on Nevada-B158 or earlier so more hoops to jump through
       
  1002 static bool has_newer_Pstack_iter = false;  // older version by default
       
  1003 #endif
       
  1004 
       
  1005 /*
       
  1006  * Class:       sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal
       
  1007  * Method:      fillCFrameList0
       
  1008  * Signature:   ([J)Lsun/jvm/hotspot/debugger/proc/ProcCFrame;
       
  1009  * Description: fills CFrame list for a given thread
       
  1010  */
       
  1011 JNIEXPORT jobject JNICALL Java_sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal_fillCFrameList0
       
  1012   (JNIEnv *env, jobject this_obj, jlongArray regsArray) {
       
  1013   jlong p_ps_prochandle = env->GetLongField(this_obj, p_ps_prochandle_ID);
       
  1014 
       
  1015   DebuggerWith2Objects dbgo2;
       
  1016   dbgo2.env  = env;
       
  1017   dbgo2.this_obj = this_obj;
       
  1018   dbgo2.obj  = NULL;
       
  1019   dbgo2.obj2 = NULL;
       
  1020 
       
  1021   jboolean isCopy;
       
  1022   jlong* ptr = env->GetLongArrayElements(regsArray, &isCopy);
       
  1023   CHECK_EXCEPTION_(0);
       
  1024 
       
  1025   prgregset_t gregs;
       
  1026   for (int i = 0; i < NPRGREG; i++) {
       
  1027      gregs[i] = (uintptr_t) ptr[i];
       
  1028   }
       
  1029 
       
  1030   env->ReleaseLongArrayElements(regsArray, ptr, JNI_ABORT);
       
  1031   CHECK_EXCEPTION_(0);
       
  1032 
       
  1033 #ifdef SOLARIS_11_B159_OR_LATER
       
  1034   // building on Nevada-B159 or later so use the new callback
       
  1035   Pstack_iter((struct ps_prochandle*) p_ps_prochandle, gregs,
       
  1036               wrapper_fill_cframe_list, &dbgo2);
       
  1037 #else
       
  1038   // building on Nevada-B158 or earlier so figure out which callback to use
       
  1039 
       
  1040   if (has_newer_Pstack_iter) {
       
  1041     // Since we're building on Nevada-B158 or earlier, we have to
       
  1042     // cast wrapper_fill_cframe_list to make the compiler happy.
       
  1043     Pstack_iter((struct ps_prochandle*) p_ps_prochandle, gregs,
       
  1044                 (proc_stack_f *)wrapper_fill_cframe_list, &dbgo2);
       
  1045   } else {
       
  1046     Pstack_iter((struct ps_prochandle*) p_ps_prochandle, gregs,
       
  1047                 fill_cframe_list, &dbgo2);
       
  1048   }
       
  1049 #endif // SOLARIS_11_B159_OR_LATER
       
  1050   return dbgo2.obj;
       
  1051 }
       
  1052 
       
  1053 /*
       
  1054  * Class:       sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal
       
  1055  * Method:      fillLoadObjectList0
       
  1056  * Signature:   (Ljava/util/List;)V
       
  1057  * Description: fills shared objects of the debuggee process/core
       
  1058  */
       
  1059 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal_fillLoadObjectList0
       
  1060   (JNIEnv *env, jobject this_obj, jobject list) {
       
  1061   DebuggerWithObject dbgo;
       
  1062   dbgo.env = env;
       
  1063   dbgo.this_obj = this_obj;
       
  1064   dbgo.obj = list;
       
  1065 
       
  1066   jlong p_ps_prochandle = env->GetLongField(this_obj, p_ps_prochandle_ID);
       
  1067   Pobject_iter((struct ps_prochandle*) p_ps_prochandle, fill_load_object_list, &dbgo);
       
  1068 }
       
  1069 
       
  1070 /*
       
  1071  * Class:       sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal
       
  1072  * Method:      readBytesFromProcess0
       
  1073  * Signature:   (JJ)[B
       
  1074  * Description: read bytes from debuggee process/core
       
  1075  */
       
  1076 JNIEXPORT jbyteArray JNICALL Java_sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal_readBytesFromProcess0
       
  1077   (JNIEnv *env, jobject this_obj, jlong address, jlong numBytes) {
       
  1078 
       
  1079   jbyteArray array = env->NewByteArray(numBytes);
       
  1080   CHECK_EXCEPTION_(0);
       
  1081   jboolean isCopy;
       
  1082   jbyte* bufPtr = env->GetByteArrayElements(array, &isCopy);
       
  1083   CHECK_EXCEPTION_(0);
       
  1084 
       
  1085   jlong p_ps_prochandle = env->GetLongField(this_obj, p_ps_prochandle_ID);
       
  1086   ps_err_e ret = ps_pread((struct ps_prochandle*) p_ps_prochandle,
       
  1087                        (psaddr_t)address, bufPtr, (size_t)numBytes);
       
  1088 
       
  1089   if (ret != PS_OK) {
       
  1090     // part of the class sharing workaround. try shared heap area
       
  1091     int classes_jsa_fd = env->GetIntField(this_obj, classes_jsa_fd_ID);
       
  1092     if (classes_jsa_fd != -1 && address != (jlong)0) {
       
  1093       print_debug("read failed at 0x%lx, attempting shared heap area\n", (long) address);
       
  1094 
       
  1095       struct FileMapHeader* pheader = (struct FileMapHeader*) env->GetLongField(this_obj, p_file_map_header_ID);
       
  1096       // walk through the shared mappings -- we just have 4 of them.
       
  1097       // so, linear walking is okay.
       
  1098       for (int m = 0; m < NUM_SHARED_MAPS; m++) {
       
  1099 
       
  1100         // We can skip the non-read-only maps. These are mapped as MAP_PRIVATE
       
  1101         // and hence will be read by libproc. Besides, the file copy may be
       
  1102         // stale because the process might have modified those pages.
       
  1103         if (pheader->_space[m]._read_only) {
       
  1104           jlong baseAddress = (jlong) (uintptr_t) pheader->_space[m]._base;
       
  1105           size_t usedSize = pheader->_space[m]._used;
       
  1106           if (address >= baseAddress && address < (baseAddress + usedSize)) {
       
  1107             // the given address falls in this shared heap area
       
  1108             print_debug("found shared map at 0x%lx\n", (long) baseAddress);
       
  1109 
       
  1110 
       
  1111             // If more data is asked than actually mapped from file, we need to zero fill
       
  1112             // till the end-of-page boundary. But, java array new does that for us. we just
       
  1113             // need to read as much as data available.
       
  1114 
       
  1115 #define MIN2(x, y) (((x) < (y))? (x) : (y))
       
  1116 
       
  1117             jlong diff = address - baseAddress;
       
  1118             jlong bytesToRead = MIN2(numBytes, usedSize - diff);
       
  1119             off_t offset = pheader->_space[m]._file_offset  + off_t(diff);
       
  1120             ssize_t bytesRead = pread(classes_jsa_fd, bufPtr, bytesToRead, offset);
       
  1121             if (bytesRead != bytesToRead) {
       
  1122               env->ReleaseByteArrayElements(array, bufPtr, JNI_ABORT);
       
  1123               print_debug("shared map read failed\n");
       
  1124               return jbyteArray(0);
       
  1125             } else {
       
  1126               print_debug("shared map read succeeded\n");
       
  1127               env->ReleaseByteArrayElements(array, bufPtr, 0);
       
  1128               return array;
       
  1129             }
       
  1130           } // is in current map
       
  1131         } // is read only map
       
  1132       } // for shared maps
       
  1133     } // classes_jsa_fd != -1
       
  1134     env->ReleaseByteArrayElements(array, bufPtr, JNI_ABORT);
       
  1135     return jbyteArray(0);
       
  1136   } else {
       
  1137     env->ReleaseByteArrayElements(array, bufPtr, 0);
       
  1138     return array;
       
  1139   }
       
  1140 }
       
  1141 
       
  1142 /*
       
  1143  * Class:       sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal
       
  1144  * Method:      writeBytesToProcess0
       
  1145  * Signature:   (JJ[B)V
       
  1146  * Description: write bytes into debugger process
       
  1147  */
       
  1148 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal_writeBytesToProcess0
       
  1149   (JNIEnv *env, jobject this_obj, jlong address, jlong numBytes, jbyteArray data) {
       
  1150   jlong p_ps_prochandle = env->GetLongField(this_obj, p_ps_prochandle_ID);
       
  1151   jboolean isCopy;
       
  1152   jbyte* ptr = env->GetByteArrayElements(data, &isCopy);
       
  1153   CHECK_EXCEPTION;
       
  1154 
       
  1155   if (ps_pwrite((struct ps_prochandle*) p_ps_prochandle, address, ptr, numBytes) != PS_OK) {
       
  1156      env->ReleaseByteArrayElements(data, ptr, JNI_ABORT);
       
  1157      THROW_NEW_DEBUGGER_EXCEPTION("Process write failed!");
       
  1158   }
       
  1159 
       
  1160   env->ReleaseByteArrayElements(data, ptr, JNI_ABORT);
       
  1161 }
       
  1162 
       
  1163 /*
       
  1164  * Class:     sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal
       
  1165  * Method:    suspend0
       
  1166  * Signature: ()V
       
  1167  */
       
  1168 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal_suspend0
       
  1169   (JNIEnv *env, jobject this_obj) {
       
  1170   jlong p_ps_prochandle = env->GetLongField(this_obj, p_ps_prochandle_ID);
       
  1171   // for now don't check return value. revisit this again.
       
  1172   Pstop((struct ps_prochandle*) p_ps_prochandle, 1000);
       
  1173 }
       
  1174 
       
  1175 /*
       
  1176  * Class:     sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal
       
  1177  * Method:    resume0
       
  1178  * Signature: ()V
       
  1179  */
       
  1180 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal_resume0
       
  1181   (JNIEnv *env, jobject this_obj) {
       
  1182   jlong p_ps_prochandle = env->GetLongField(this_obj, p_ps_prochandle_ID);
       
  1183   // for now don't check return value. revisit this again.
       
  1184   Psetrun((struct ps_prochandle*) p_ps_prochandle, 0, PRCFAULT|PRSTOP);
       
  1185 }
       
  1186 
       
  1187 /*
       
  1188   * Class:       sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal
       
  1189   * Method:      lookupByName0
       
  1190   * Signature:   (Ljava/lang/String;Ljava/lang/String;)J
       
  1191   * Description: symbol lookup by name
       
  1192 */
       
  1193 JNIEXPORT jlong JNICALL Java_sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal_lookupByName0
       
  1194    (JNIEnv *env, jobject this_obj, jstring objectName, jstring symbolName) {
       
  1195    jlong p_ps_prochandle;
       
  1196    p_ps_prochandle = env->GetLongField(this_obj, p_ps_prochandle_ID);
       
  1197 
       
  1198    jboolean isCopy;
       
  1199    const char* objectName_cstr = NULL;
       
  1200    if (objectName != NULL) {
       
  1201      objectName_cstr = env->GetStringUTFChars(objectName, &isCopy);
       
  1202      CHECK_EXCEPTION_(0);
       
  1203    } else {
       
  1204      objectName_cstr = PR_OBJ_EVERY;
       
  1205    }
       
  1206 
       
  1207    const char* symbolName_cstr = env->GetStringUTFChars(symbolName, &isCopy);
       
  1208    CHECK_EXCEPTION_(0);
       
  1209 
       
  1210    psaddr_t symbol_addr = (psaddr_t) 0;
       
  1211    ps_pglobal_lookup((struct ps_prochandle*) p_ps_prochandle,  objectName_cstr,
       
  1212                     symbolName_cstr, &symbol_addr);
       
  1213 
       
  1214    if (symbol_addr == 0) {
       
  1215       print_debug("lookup for %s in %s failed\n", symbolName_cstr, objectName_cstr);
       
  1216    }
       
  1217 
       
  1218    if (objectName_cstr != PR_OBJ_EVERY) {
       
  1219      env->ReleaseStringUTFChars(objectName, objectName_cstr);
       
  1220    }
       
  1221    env->ReleaseStringUTFChars(symbolName, symbolName_cstr);
       
  1222    return (jlong) (uintptr_t) symbol_addr;
       
  1223 }
       
  1224 
       
  1225 /*
       
  1226  * Class:       sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal
       
  1227  * Method:      lookupByAddress0
       
  1228  * Signature:   (J)Lsun/jvm/hotspot/debugger/cdbg/ClosestSymbol;
       
  1229  * Description: lookup symbol name for a given address
       
  1230  */
       
  1231 JNIEXPORT jobject JNICALL Java_sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal_lookupByAddress0
       
  1232    (JNIEnv *env, jobject this_obj, jlong address) {
       
  1233    jlong p_ps_prochandle;
       
  1234    p_ps_prochandle = env->GetLongField(this_obj, p_ps_prochandle_ID);
       
  1235 
       
  1236    char nameBuf[SYMBOL_BUF_SIZE + 1];
       
  1237    GElf_Sym sym;
       
  1238    int res = Plookup_by_addr((struct ps_prochandle*) p_ps_prochandle, (uintptr_t) address,
       
  1239                                  nameBuf, sizeof(nameBuf), &sym);
       
  1240    if (res != 0) { // failed
       
  1241       return 0;
       
  1242    }
       
  1243 
       
  1244    jstring resSym = env->NewStringUTF(nameBuf);
       
  1245    CHECK_EXCEPTION_(0);
       
  1246 
       
  1247    return env->CallObjectMethod(this_obj, createClosestSymbol_ID, resSym, (address - sym.st_value));
       
  1248 }
       
  1249 
       
  1250 /*
       
  1251  * Class:     sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal
       
  1252  * Method:    demangle0
       
  1253  * Signature: (Ljava/lang/String;)Ljava/lang/String;
       
  1254  */
       
  1255 JNIEXPORT jstring JNICALL Java_sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal_demangle0
       
  1256   (JNIEnv *env, jobject this_object, jstring name) {
       
  1257   jboolean isCopy;
       
  1258   const char* ptr = env->GetStringUTFChars(name, &isCopy);
       
  1259   CHECK_EXCEPTION_(NULL);
       
  1260   char  buf[2*SYMBOL_BUF_SIZE + 1];
       
  1261   jstring res = 0;
       
  1262   if (cplus_demangle((char*) ptr, buf, sizeof(buf)) != DEMANGLE_ESPACE) {
       
  1263     res = env->NewStringUTF(buf);
       
  1264   } else {
       
  1265     res = name;
       
  1266   }
       
  1267   env->ReleaseStringUTFChars(name, ptr);
       
  1268   return res;
       
  1269 }
       
  1270 
       
  1271 #ifndef SOLARIS_11_B159_OR_LATER
       
  1272 // Determine if the OS we're running on has the newer version
       
  1273 // of libproc's Pstack_iter.
       
  1274 //
       
  1275 // Set env var PSTACK_ITER_DEBUG=true to debug this logic.
       
  1276 // Set env var PSTACK_ITER_DEBUG_RELEASE to simulate a 'release' value.
       
  1277 // Set env var PSTACK_ITER_DEBUG_VERSION to simulate a 'version' value.
       
  1278 //
       
  1279 // frankenputer 'uname -r -v': 5.10 Generic_141445-09
       
  1280 // jurassic 'uname -r -v':     5.11 snv_164
       
  1281 // lonepeak 'uname -r -v':     5.11 snv_127
       
  1282 //
       
  1283 static void set_has_newer_Pstack_iter(JNIEnv *env) {
       
  1284   static bool done_set = false;
       
  1285 
       
  1286   if (done_set) {
       
  1287     // already set has_newer_Pstack_iter
       
  1288     return;
       
  1289   }
       
  1290 
       
  1291   struct utsname name;
       
  1292   if (uname(&name) == -1) {
       
  1293     THROW_NEW_DEBUGGER_EXCEPTION("uname() failed!");
       
  1294   }
       
  1295   dprintf_2("release='%s'  version='%s'\n", name.release, name.version);
       
  1296 
       
  1297   if (_Pstack_iter_debug) {
       
  1298     char *override = getenv("PSTACK_ITER_DEBUG_RELEASE");
       
  1299     if (override != NULL) {
       
  1300       strncpy(name.release, override, SYS_NMLN - 1);
       
  1301       name.release[SYS_NMLN - 2] = '\0';
       
  1302       dprintf_2("overriding with release='%s'\n", name.release);
       
  1303     }
       
  1304     override = getenv("PSTACK_ITER_DEBUG_VERSION");
       
  1305     if (override != NULL) {
       
  1306       strncpy(name.version, override, SYS_NMLN - 1);
       
  1307       name.version[SYS_NMLN - 2] = '\0';
       
  1308       dprintf_2("overriding with version='%s'\n", name.version);
       
  1309     }
       
  1310   }
       
  1311 
       
  1312   // the major number corresponds to the old SunOS major number
       
  1313   int major = atoi(name.release);
       
  1314   if (major >= 6) {
       
  1315     dprintf_2("release is SunOS 6 or later\n");
       
  1316     has_newer_Pstack_iter = true;
       
  1317     done_set = true;
       
  1318     return;
       
  1319   }
       
  1320   if (major < 5) {
       
  1321     dprintf_2("release is SunOS 4 or earlier\n");
       
  1322     done_set = true;
       
  1323     return;
       
  1324   }
       
  1325 
       
  1326   // some SunOS 5.* build so now check for Solaris versions
       
  1327   char *dot = strchr(name.release, '.');
       
  1328   int minor = 0;
       
  1329   if (dot != NULL) {
       
  1330     // release is major.minor format
       
  1331     *dot = NULL;
       
  1332     minor = atoi(dot + 1);
       
  1333   }
       
  1334 
       
  1335   if (minor <= 10) {
       
  1336     dprintf_2("release is Solaris 10 or earlier\n");
       
  1337     done_set = true;
       
  1338     return;
       
  1339   } else if (minor >= 12) {
       
  1340     dprintf_2("release is Solaris 12 or later\n");
       
  1341     has_newer_Pstack_iter = true;
       
  1342     done_set = true;
       
  1343     return;
       
  1344   }
       
  1345 
       
  1346   // some Solaris 11 build so now check for internal build numbers
       
  1347   if (strncmp(name.version, "snv_", 4) != 0) {
       
  1348     dprintf_2("release is Solaris 11 post-GA or later\n");
       
  1349     has_newer_Pstack_iter = true;
       
  1350     done_set = true;
       
  1351     return;
       
  1352   }
       
  1353 
       
  1354   // version begins with "snv_" so a pre-GA build of Solaris 11
       
  1355   int build = atoi(&name.version[4]);
       
  1356   if (build >= 159) {
       
  1357     dprintf_2("release is Nevada-B159 or later\n");
       
  1358     has_newer_Pstack_iter = true;
       
  1359   } else {
       
  1360     dprintf_2("release is Nevada-B158 or earlier\n");
       
  1361   }
       
  1362 
       
  1363   done_set = true;
       
  1364 }
       
  1365 #endif // !SOLARIS_11_B159_OR_LATER
       
  1366 
       
  1367 /*
       
  1368  * Class:       sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal
       
  1369  * Method:      initIDs
       
  1370  * Signature:   ()V
       
  1371  * Description: get JNI ids for fields and methods of ProcDebuggerLocal class
       
  1372  */
       
  1373 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal_initIDs
       
  1374   (JNIEnv *env, jclass clazz) {
       
  1375   _libsaproc_debug = getenv("LIBSAPROC_DEBUG") != NULL;
       
  1376   if (_libsaproc_debug) {
       
  1377      // propagate debug mode to libproc.so
       
  1378      static const char* var = "LIBPROC_DEBUG=1";
       
  1379      putenv((char*)var);
       
  1380   }
       
  1381 
       
  1382   void* libproc_handle = dlopen("libproc.so", RTLD_LAZY | RTLD_GLOBAL);
       
  1383   if (libproc_handle == 0)
       
  1384      THROW_NEW_DEBUGGER_EXCEPTION("can't load libproc.so, if you are using Solaris 5.7 or below, copy libproc.so from 5.8!");
       
  1385 
       
  1386 #ifndef SOLARIS_11_B159_OR_LATER
       
  1387   _Pstack_iter_debug = getenv("PSTACK_ITER_DEBUG") != NULL;
       
  1388 
       
  1389   set_has_newer_Pstack_iter(env);
       
  1390   CHECK_EXCEPTION;
       
  1391   dprintf_2("has_newer_Pstack_iter=%d\n", has_newer_Pstack_iter);
       
  1392 #endif
       
  1393 
       
  1394   p_ps_prochandle_ID = env->GetFieldID(clazz, "p_ps_prochandle", "J");
       
  1395   CHECK_EXCEPTION;
       
  1396 
       
  1397   libthread_db_handle_ID = env->GetFieldID(clazz, "libthread_db_handle", "J");
       
  1398   CHECK_EXCEPTION;
       
  1399 
       
  1400   p_td_thragent_t_ID = env->GetFieldID(clazz, "p_td_thragent_t", "J");
       
  1401   CHECK_EXCEPTION;
       
  1402 
       
  1403   p_td_init_ID = env->GetFieldID(clazz, "p_td_init", "J");
       
  1404   CHECK_EXCEPTION;
       
  1405 
       
  1406   p_td_ta_new_ID = env->GetFieldID(clazz, "p_td_ta_new", "J");
       
  1407   CHECK_EXCEPTION;
       
  1408 
       
  1409   p_td_ta_delete_ID = env->GetFieldID(clazz, "p_td_ta_delete", "J");
       
  1410   CHECK_EXCEPTION;
       
  1411 
       
  1412   p_td_ta_thr_iter_ID = env->GetFieldID(clazz, "p_td_ta_thr_iter", "J");
       
  1413   CHECK_EXCEPTION;
       
  1414 
       
  1415   p_td_thr_get_info_ID = env->GetFieldID(clazz, "p_td_thr_get_info", "J");
       
  1416   CHECK_EXCEPTION;
       
  1417 
       
  1418   p_td_ta_map_id2thr_ID = env->GetFieldID(clazz, "p_td_ta_map_id2thr", "J");
       
  1419   CHECK_EXCEPTION;
       
  1420 
       
  1421   p_td_thr_getgregs_ID = env->GetFieldID(clazz, "p_td_thr_getgregs", "J");
       
  1422   CHECK_EXCEPTION;
       
  1423 
       
  1424   getThreadForThreadId_ID = env->GetMethodID(clazz,
       
  1425                             "getThreadForThreadId", "(J)Lsun/jvm/hotspot/debugger/ThreadProxy;");
       
  1426   CHECK_EXCEPTION;
       
  1427 
       
  1428   pcRegIndex_ID = env->GetFieldID(clazz, "pcRegIndex", "I");
       
  1429   CHECK_EXCEPTION;
       
  1430 
       
  1431   fpRegIndex_ID = env->GetFieldID(clazz, "fpRegIndex", "I");
       
  1432   CHECK_EXCEPTION;
       
  1433 
       
  1434   createSenderFrame_ID = env->GetMethodID(clazz,
       
  1435                             "createSenderFrame", "(Lsun/jvm/hotspot/debugger/proc/ProcCFrame;JJ)Lsun/jvm/hotspot/debugger/proc/ProcCFrame;");
       
  1436   CHECK_EXCEPTION;
       
  1437 
       
  1438   createLoadObject_ID = env->GetMethodID(clazz,
       
  1439                             "createLoadObject", "(Ljava/lang/String;JJ)Lsun/jvm/hotspot/debugger/cdbg/LoadObject;");
       
  1440   CHECK_EXCEPTION;
       
  1441 
       
  1442   createClosestSymbol_ID = env->GetMethodID(clazz,
       
  1443                             "createClosestSymbol", "(Ljava/lang/String;J)Lsun/jvm/hotspot/debugger/cdbg/ClosestSymbol;");
       
  1444   CHECK_EXCEPTION;
       
  1445 
       
  1446   jclass list_clazz = env->FindClass("java/util/List");
       
  1447   CHECK_EXCEPTION;
       
  1448   listAdd_ID = env->GetMethodID(list_clazz, "add", "(Ljava/lang/Object;)Z");
       
  1449   CHECK_EXCEPTION;
       
  1450 
       
  1451   // part of the class sharing workaround
       
  1452   classes_jsa_fd_ID = env->GetFieldID(clazz, "classes_jsa_fd", "I");
       
  1453   CHECK_EXCEPTION;
       
  1454   p_file_map_header_ID = env->GetFieldID(clazz, "p_file_map_header", "J");
       
  1455   CHECK_EXCEPTION;
       
  1456 }