Merge

Sun, 17 Mar 2013 08:57:56 -0700

author
dcubed
date
Sun, 17 Mar 2013 08:57:56 -0700
changeset 4754
82ab039b9680
parent 4749
7ae04e71af90
parent 4753
919a5f9f36a9
child 4755
117bb0519114

Merge

src/share/vm/memory/metaspace.cpp file | annotate | diff | comparison | revisions
     1.1 --- a/agent/src/os/bsd/MacosxDebuggerLocal.m	Fri Mar 15 11:44:33 2013 -0700
     1.2 +++ b/agent/src/os/bsd/MacosxDebuggerLocal.m	Sun Mar 17 08:57:56 2013 -0700
     1.3 @@ -1,5 +1,5 @@
     1.4  /*
     1.5 - * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
     1.6 + * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
     1.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     1.8   *
     1.9   * This code is free software; you can redistribute it and/or modify it
    1.10 @@ -40,12 +40,34 @@
    1.11  #import <errno.h>
    1.12  #import <sys/types.h>
    1.13  #import <sys/ptrace.h>
    1.14 +#include "libproc_impl.h"
    1.15  
    1.16 -jboolean debug = JNI_FALSE;
    1.17 +#define UNSUPPORTED_ARCH "Unsupported architecture!"
    1.18 +
    1.19 +#if defined(x86_64) && !defined(amd64)
    1.20 +#define amd64 1
    1.21 +#endif
    1.22 +
    1.23 +#if amd64
    1.24 +#include "sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext.h"
    1.25 +#else
    1.26 +#error UNSUPPORTED_ARCH
    1.27 +#endif
    1.28  
    1.29  static jfieldID symbolicatorID = 0; // set in _init0
    1.30  static jfieldID taskID = 0; // set in _init0
    1.31  
    1.32 +static jfieldID p_ps_prochandle_ID = 0;
    1.33 +static jfieldID loadObjectList_ID = 0;
    1.34 +static jmethodID listAdd_ID = 0;
    1.35 +
    1.36 +static jmethodID createClosestSymbol_ID = 0;
    1.37 +static jmethodID createLoadObject_ID = 0;
    1.38 +static jmethodID getJavaThreadsInfo_ID = 0;
    1.39 +
    1.40 +// indicator if thread id (lwpid_t) was set
    1.41 +static bool _threads_filled = false;
    1.42 +
    1.43  static void putSymbolicator(JNIEnv *env, jobject this_obj, id symbolicator) {
    1.44    (*env)->SetLongField(env, this_obj, symbolicatorID, (jlong)(intptr_t)symbolicator);
    1.45  }
    1.46 @@ -76,6 +98,11 @@
    1.47    (*env)->ThrowNew(env, (*env)->FindClass(env, "sun/jvm/hotspot/debugger/DebuggerException"), errMsg);
    1.48  }
    1.49  
    1.50 +static struct ps_prochandle* get_proc_handle(JNIEnv* env, jobject this_obj) {
    1.51 +  jlong ptr = (*env)->GetLongField(env, this_obj, p_ps_prochandle_ID);
    1.52 +  return (struct ps_prochandle*)(intptr_t)ptr;
    1.53 +}
    1.54 +
    1.55  #if defined(__i386__)
    1.56      #define hsdb_thread_state_t     x86_thread_state32_t
    1.57      #define hsdb_float_state_t      x86_float_state32_t
    1.58 @@ -91,7 +118,7 @@
    1.59      #define HSDB_THREAD_STATE_COUNT x86_THREAD_STATE64_COUNT
    1.60      #define HSDB_FLOAT_STATE_COUNT  x86_FLOAT_STATE64_COUNT
    1.61  #else
    1.62 -    #error "Unsupported architecture"
    1.63 +    #error UNSUPPORTED_ARCH
    1.64  #endif
    1.65  
    1.66  /*
    1.67 @@ -104,6 +131,66 @@
    1.68    symbolicatorID = (*env)->GetFieldID(env, cls, "symbolicator", "J");
    1.69    taskID = (*env)->GetFieldID(env, cls, "task", "J");
    1.70    CHECK_EXCEPTION;
    1.71 +
    1.72 +  // for core file
    1.73 +  p_ps_prochandle_ID = (*env)->GetFieldID(env, cls, "p_ps_prochandle", "J");
    1.74 +  CHECK_EXCEPTION;
    1.75 +  loadObjectList_ID = (*env)->GetFieldID(env, cls, "loadObjectList", "Ljava/util/List;");
    1.76 +  CHECK_EXCEPTION;
    1.77 +
    1.78 +  // methods we use
    1.79 +  createClosestSymbol_ID = (*env)->GetMethodID(env, cls, "createClosestSymbol",
    1.80 +                    "(Ljava/lang/String;J)Lsun/jvm/hotspot/debugger/cdbg/ClosestSymbol;");
    1.81 +  CHECK_EXCEPTION;
    1.82 +  createLoadObject_ID = (*env)->GetMethodID(env, cls, "createLoadObject",
    1.83 +                    "(Ljava/lang/String;JJ)Lsun/jvm/hotspot/debugger/cdbg/LoadObject;");
    1.84 +  CHECK_EXCEPTION;
    1.85 +
    1.86 +  // java.util.List method we call
    1.87 +  jclass listClass = (*env)->FindClass(env, "java/util/List");
    1.88 +  CHECK_EXCEPTION;
    1.89 +  listAdd_ID = (*env)->GetMethodID(env, listClass, "add", "(Ljava/lang/Object;)Z");
    1.90 +  CHECK_EXCEPTION;
    1.91 +  getJavaThreadsInfo_ID = (*env)->GetMethodID(env, cls, "getJavaThreadsInfo",
    1.92 +                                                     "()[J");
    1.93 +  CHECK_EXCEPTION;
    1.94 +
    1.95 +  init_libproc(getenv("LIBSAPROC_DEBUG") != NULL);
    1.96 +}
    1.97 +
    1.98 +JNIEXPORT jint JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_getAddressSize
    1.99 +  (JNIEnv *env, jclass cls)
   1.100 +{
   1.101 +#ifdef _LP64
   1.102 +  return 8;
   1.103 +#else
   1.104 +  #error UNSUPPORTED_ARCH
   1.105 +#endif
   1.106 +}
   1.107 +
   1.108 +/** called by Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_lookupByName0 */
   1.109 +jlong lookupByNameIncore(
   1.110 +  JNIEnv *env, struct ps_prochandle *ph, jobject this_obj, jstring objectName, jstring symbolName)
   1.111 +{
   1.112 +  const char *objectName_cstr, *symbolName_cstr;
   1.113 +  jlong addr;
   1.114 +  jboolean isCopy;
   1.115 +  objectName_cstr = NULL;
   1.116 +  if (objectName != NULL) {
   1.117 +    objectName_cstr = (*env)->GetStringUTFChars(env, objectName, &isCopy);
   1.118 +    CHECK_EXCEPTION_(0);
   1.119 +  }
   1.120 +  symbolName_cstr = (*env)->GetStringUTFChars(env, symbolName, &isCopy);
   1.121 +  CHECK_EXCEPTION_(0);
   1.122 +
   1.123 +  print_debug("look for %s \n", symbolName_cstr);
   1.124 +  addr = (jlong) lookup_symbol(ph, objectName_cstr, symbolName_cstr);
   1.125 +
   1.126 +  if (objectName_cstr != NULL) {
   1.127 +    (*env)->ReleaseStringUTFChars(env, objectName, objectName_cstr);
   1.128 +  }
   1.129 +  (*env)->ReleaseStringUTFChars(env, symbolName, symbolName_cstr);
   1.130 +  return addr;
   1.131  }
   1.132  
   1.133  /*
   1.134 @@ -116,14 +203,17 @@
   1.135    JNIEnv *env, jobject this_obj, 
   1.136    jstring objectName, jstring symbolName) 
   1.137  {
   1.138 +  struct ps_prochandle* ph = get_proc_handle(env, this_obj);
   1.139 +  if (ph->core != NULL) {
   1.140 +    return lookupByNameIncore(env, ph, this_obj, objectName, symbolName);
   1.141 +  }
   1.142 +
   1.143    jlong address = 0;
   1.144  
   1.145  JNF_COCOA_ENTER(env);
   1.146    NSString *symbolNameString = JNFJavaToNSString(env, symbolName);
   1.147  
   1.148 -  if (debug) {
   1.149 -    printf("lookupInProcess called for %s\n", [symbolNameString UTF8String]);
   1.150 -  }
   1.151 +  print_debug("lookupInProcess called for %s\n", [symbolNameString UTF8String]);
   1.152  
   1.153    id symbolicator = getSymbolicator(env, this_obj);
   1.154    if (symbolicator != nil) {
   1.155 @@ -131,9 +221,7 @@
   1.156      address = (jlong) dynamicCall(symbolicator, @selector(addressForSymbol:), symbolNameString);
   1.157    }
   1.158  
   1.159 -  if (debug) {
   1.160 -    printf("address of symbol %s = %llx\n", [symbolNameString UTF8String], address);
   1.161 -  }
   1.162 +  print_debug("address of symbol %s = %llx\n", [symbolNameString UTF8String], address);
   1.163  JNF_COCOA_EXIT(env);
   1.164  
   1.165    return address;
   1.166 @@ -141,6 +229,42 @@
   1.167  
   1.168  /*
   1.169   * Class:     sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
   1.170 + * Method:    lookupByAddress0
   1.171 + * Signature: (J)Lsun/jvm/hotspot/debugger/cdbg/ClosestSymbol;
   1.172 + */
   1.173 +JNIEXPORT jobject JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_lookupByAddress0
   1.174 +  (JNIEnv *env, jobject this_obj, jlong addr) {
   1.175 +  uintptr_t offset;
   1.176 +  const char* sym = NULL;
   1.177 +
   1.178 +  struct ps_prochandle* ph = get_proc_handle(env, this_obj);
   1.179 +  sym = symbol_for_pc(ph, (uintptr_t) addr, &offset);
   1.180 +  if (sym == NULL) return 0;
   1.181 +  return (*env)->CallObjectMethod(env, this_obj, createClosestSymbol_ID,
   1.182 +                          (*env)->NewStringUTF(env, sym), (jlong)offset);
   1.183 +}
   1.184 +
   1.185 +/** called from Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_readBytesFromProcess0 */
   1.186 +jbyteArray readBytesFromCore(
   1.187 +  JNIEnv *env, struct ps_prochandle *ph, jobject this_obj, jlong addr, jlong numBytes)
   1.188 +{
   1.189 +  jboolean isCopy;
   1.190 +  jbyteArray array;
   1.191 +  jbyte *bufPtr;
   1.192 +  ps_err_e err;
   1.193 +
   1.194 +  array = (*env)->NewByteArray(env, numBytes);
   1.195 +  CHECK_EXCEPTION_(0);
   1.196 +  bufPtr = (*env)->GetByteArrayElements(env, array, &isCopy);
   1.197 +  CHECK_EXCEPTION_(0);
   1.198 +
   1.199 +  err = ps_pread(ph, (psaddr_t) (uintptr_t)addr, bufPtr, numBytes);
   1.200 +  (*env)->ReleaseByteArrayElements(env, array, bufPtr, 0);
   1.201 +  return (err == PS_OK)? array : 0;
   1.202 +}
   1.203 +
   1.204 +/*
   1.205 + * Class:     sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
   1.206   * Method:    readBytesFromProcess0
   1.207   * Signature: (JJ)Lsun/jvm/hotspot/debugger/ReadResult;
   1.208   */
   1.209 @@ -149,12 +273,15 @@
   1.210    JNIEnv *env, jobject this_obj, 
   1.211    jlong addr, jlong numBytes) 
   1.212  {
   1.213 -  if (debug) printf("readBytesFromProcess called. addr = %llx numBytes = %lld\n", addr, numBytes);
   1.214 +  print_debug("readBytesFromProcess called. addr = %llx numBytes = %lld\n", addr, numBytes);
   1.215  
   1.216    // must allocate storage instead of using former parameter buf
   1.217 -  jboolean isCopy;
   1.218    jbyteArray array;
   1.219 -  jbyte *bufPtr;
   1.220 +
   1.221 +  struct ps_prochandle* ph = get_proc_handle(env, this_obj);
   1.222 +  if (ph->core != NULL) {
   1.223 +    return readBytesFromCore(env, ph, this_obj, addr, numBytes);
   1.224 +  }
   1.225  
   1.226    array = (*env)->NewByteArray(env, numBytes);
   1.227    CHECK_EXCEPTION_(0);
   1.228 @@ -189,7 +316,7 @@
   1.229      // assume all failures are unmapped pages
   1.230    }
   1.231  
   1.232 -  if (debug) fprintf(stderr, "%ld pages\n", pageCount);
   1.233 +  print_debug("%ld pages\n", pageCount);
   1.234  	
   1.235    remaining = numBytes;
   1.236  	
   1.237 @@ -207,7 +334,7 @@
   1.238      }
   1.239  
   1.240      if (mapped[i]) {
   1.241 -      if (debug) fprintf(stderr, "page %d mapped (len %ld start %ld)\n", i, len, start);
   1.242 +      print_debug("page %d mapped (len %ld start %ld)\n", i, len, start);
   1.243        (*env)->SetByteArrayRegion(env, array, 0, len, ((jbyte *) pages[i] + start));
   1.244        vm_deallocate(mach_task_self(), pages[i], vm_page_size);
   1.245      }
   1.246 @@ -220,6 +347,115 @@
   1.247    return array;
   1.248  }
   1.249  
   1.250 +/** Only used for core file reading, set thread_id for threads which is got after core file parsed.
   1.251 +  * Thread context is available in Mach-O core file but thread id is not. We can get thread id
   1.252 +  * from Threads which store all java threads information when they are created. Here we can identify
   1.253 +  * them as java threads by checking if a thread's rsp or rbp within a java thread's stack.
   1.254 +  * Note Macosx uses unique_thread_id which is different from other platforms though printed ids
   1.255 +  * are still pthread id. Function BsdDebuggerLocal.getJavaThreadsInfo returns an array of long
   1.256 +  * integers to host all java threads' id, stack_start, stack_end as:
   1.257 +  * [uid0, stack_start0, stack_end0, uid1, stack_start1, stack_end1, ...]
   1.258 +  *
   1.259 +  * The work cannot be done at init0 since Threads is not available yet(VM not initialized yet). 
   1.260 +  * This function should be called only once if succeeded
   1.261 +  */ 
   1.262 +bool fill_java_threads(JNIEnv* env, jobject this_obj, struct ps_prochandle* ph) {
   1.263 +  int n = 0, i = 0, j;
   1.264 +  struct reg regs;
   1.265 +  
   1.266 +  jlongArray thrinfos = (*env)->CallObjectMethod(env, this_obj, getJavaThreadsInfo_ID);
   1.267 +  CHECK_EXCEPTION_(false);
   1.268 +  int len = (int)(*env)->GetArrayLength(env, thrinfos);
   1.269 +  uint64_t* cinfos = (uint64_t *)(*env)->GetLongArrayElements(env, thrinfos, NULL);
   1.270 +  CHECK_EXCEPTION_(false); 
   1.271 +  n = get_num_threads(ph);
   1.272 +  print_debug("fill_java_threads called, num_of_thread = %d\n", n);
   1.273 +  for (i = 0; i < n; i++) {
   1.274 +    if (!get_nth_lwp_regs(ph, i, &regs)) {
   1.275 +      print_debug("Could not get regs of thread %d, already set!\n", i);
   1.276 +      return false;
   1.277 +    }
   1.278 +    for (j = 0; j < len; j += 3) {
   1.279 +      lwpid_t  uid = cinfos[j];
   1.280 +      uint64_t beg = cinfos[j + 1];
   1.281 +      uint64_t end = cinfos[j + 2]; 
   1.282 +      if ((regs.r_rsp < end && regs.r_rsp >= beg) ||
   1.283 +          (regs.r_rbp < end && regs.r_rbp >= beg)) {
   1.284 +        set_lwp_id(ph, i, uid);
   1.285 +        break;
   1.286 +      }
   1.287 +    }
   1.288 +  }
   1.289 +  (*env)->ReleaseLongArrayElements(env, thrinfos, (jlong*)cinfos, 0);
   1.290 +  CHECK_EXCEPTION_(false);
   1.291 +  return true;
   1.292 +}
   1.293 +
   1.294 +/* For core file only, called from
   1.295 + * Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_getThreadIntegerRegisterSet0
   1.296 + */
   1.297 +jlongArray getThreadIntegerRegisterSetFromCore(JNIEnv *env, jobject this_obj, long lwp_id) {
   1.298 +  if (!_threads_filled)  {
   1.299 +    if (!fill_java_threads(env, this_obj, get_proc_handle(env, this_obj))) {
   1.300 +      throw_new_debugger_exception(env, "Failed to fill in threads");
   1.301 +      return 0;
   1.302 +    } else {
   1.303 +      _threads_filled = true;
   1.304 +    }
   1.305 +  }
   1.306 +
   1.307 +  struct reg gregs;
   1.308 +  jboolean isCopy;
   1.309 +  jlongArray array;
   1.310 +  jlong *regs;
   1.311 +
   1.312 +  struct ps_prochandle* ph = get_proc_handle(env, this_obj);
   1.313 +  if (get_lwp_regs(ph, lwp_id, &gregs) != true) {
   1.314 +    THROW_NEW_DEBUGGER_EXCEPTION_("get_thread_regs failed for a lwp", 0);
   1.315 +  }
   1.316 +
   1.317 +#undef NPRGREG
   1.318 +#undef REG_INDEX
   1.319 +#if amd64
   1.320 +#define NPRGREG sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_NPRGREG
   1.321 +#define REG_INDEX(reg) sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_##reg
   1.322 +
   1.323 +  array = (*env)->NewLongArray(env, NPRGREG);
   1.324 +  CHECK_EXCEPTION_(0);
   1.325 +  regs = (*env)->GetLongArrayElements(env, array, &isCopy);
   1.326 +
   1.327 +  regs[REG_INDEX(R15)] = gregs.r_r15;
   1.328 +  regs[REG_INDEX(R14)] = gregs.r_r14;
   1.329 +  regs[REG_INDEX(R13)] = gregs.r_r13;
   1.330 +  regs[REG_INDEX(R12)] = gregs.r_r12;
   1.331 +  regs[REG_INDEX(RBP)] = gregs.r_rbp;
   1.332 +  regs[REG_INDEX(RBX)] = gregs.r_rbx;
   1.333 +  regs[REG_INDEX(R11)] = gregs.r_r11;
   1.334 +  regs[REG_INDEX(R10)] = gregs.r_r10;
   1.335 +  regs[REG_INDEX(R9)]  = gregs.r_r9;
   1.336 +  regs[REG_INDEX(R8)]  = gregs.r_r8;
   1.337 +  regs[REG_INDEX(RAX)] = gregs.r_rax;
   1.338 +  regs[REG_INDEX(RCX)] = gregs.r_rcx;
   1.339 +  regs[REG_INDEX(RDX)] = gregs.r_rdx;
   1.340 +  regs[REG_INDEX(RSI)] = gregs.r_rsi;
   1.341 +  regs[REG_INDEX(RDI)] = gregs.r_rdi;
   1.342 +  regs[REG_INDEX(RIP)] = gregs.r_rip;
   1.343 +  regs[REG_INDEX(CS)]  = gregs.r_cs;
   1.344 +  regs[REG_INDEX(RSP)] = gregs.r_rsp;
   1.345 +  regs[REG_INDEX(SS)]  = gregs.r_ss;
   1.346 +  regs[REG_INDEX(FSBASE)] = 0;
   1.347 +  regs[REG_INDEX(GSBASE)] = 0;
   1.348 +  regs[REG_INDEX(DS)] = gregs.r_ds;
   1.349 +  regs[REG_INDEX(ES)] = gregs.r_es;
   1.350 +  regs[REG_INDEX(FS)] = gregs.r_fs;
   1.351 +  regs[REG_INDEX(GS)] = gregs.r_gs;
   1.352 +  regs[REG_INDEX(TRAPNO)] = gregs.r_trapno;
   1.353 +  regs[REG_INDEX(RFL)]    = gregs.r_rflags;
   1.354 +
   1.355 +#endif /* amd64 */
   1.356 +  (*env)->ReleaseLongArrayElements(env, array, regs, JNI_COMMIT);
   1.357 +  return array;
   1.358 +}
   1.359  
   1.360  /*
   1.361   * Lookup the thread_t that corresponds to the given thread_id.
   1.362 @@ -232,9 +468,7 @@
   1.363   */
   1.364  thread_t
   1.365  lookupThreadFromThreadId(task_t task, jlong thread_id) {
   1.366 -  if (debug) {
   1.367 -    printf("lookupThreadFromThreadId thread_id=0x%llx\n", thread_id);
   1.368 -  }
   1.369 +  print_debug("lookupThreadFromThreadId thread_id=0x%llx\n", thread_id);
   1.370    
   1.371    thread_array_t thread_list = NULL;
   1.372    mach_msg_type_number_t thread_list_count = 0;
   1.373 @@ -244,9 +478,7 @@
   1.374    // get the list of all the send rights
   1.375    kern_return_t result = task_threads(task, &thread_list, &thread_list_count);
   1.376    if (result != KERN_SUCCESS) {
   1.377 -    if (debug) {
   1.378 -      printf("task_threads returned 0x%x\n", result);
   1.379 -    }
   1.380 +    print_debug("task_threads returned 0x%x\n", result);
   1.381      return 0;
   1.382    }
   1.383    
   1.384 @@ -257,9 +489,7 @@
   1.385      // get the THREAD_IDENTIFIER_INFO for the send right
   1.386      result = thread_info(thread_list[i], THREAD_IDENTIFIER_INFO, (thread_info_t) &m_ident_info, &count);
   1.387      if (result != KERN_SUCCESS) {
   1.388 -      if (debug) {
   1.389 -        printf("thread_info returned 0x%x\n", result);
   1.390 -      }
   1.391 +      print_debug("thread_info returned 0x%x\n", result);
   1.392        break;
   1.393      }
   1.394      
   1.395 @@ -288,15 +518,17 @@
   1.396    JNIEnv *env, jobject this_obj, 
   1.397    jlong thread_id) 
   1.398  {
   1.399 -  if (debug)
   1.400 -    printf("getThreadRegisterSet0 called\n");
   1.401 +  print_debug("getThreadRegisterSet0 called\n");
   1.402 +
   1.403 +  struct ps_prochandle* ph = get_proc_handle(env, this_obj);
   1.404 +  if (ph->core != NULL) {
   1.405 +    return getThreadIntegerRegisterSetFromCore(env, this_obj, thread_id);
   1.406 +  }
   1.407  
   1.408    kern_return_t result;
   1.409    thread_t tid;
   1.410    mach_msg_type_number_t count = HSDB_THREAD_STATE_COUNT;
   1.411    hsdb_thread_state_t state;
   1.412 -  unsigned int *r;
   1.413 -  int i;
   1.414    jlongArray registerArray;
   1.415    jlong *primitiveArray;
   1.416    task_t gTask = getTask(env, this_obj);
   1.417 @@ -306,97 +538,56 @@
   1.418    result = thread_get_state(tid, HSDB_THREAD_STATE, (thread_state_t)&state, &count);
   1.419  
   1.420    if (result != KERN_SUCCESS) {
   1.421 -    if (debug)
   1.422 -      printf("getregs: thread_get_state(%d) failed (%d)\n", tid, result);
   1.423 +    print_error("getregs: thread_get_state(%d) failed (%d)\n", tid, result);
   1.424      return NULL;
   1.425    }
   1.426  
   1.427 -  // 40 32-bit registers on ppc, 16 on x86. 
   1.428 -  // Output order is the same as the order in the ppc_thread_state/i386_thread_state struct.
   1.429 -#if defined(__i386__)
   1.430 -	r = (unsigned int *)&state;
   1.431 -	registerArray = (*env)->NewLongArray(env, 8);
   1.432 -	primitiveArray = (*env)->GetLongArrayElements(env, registerArray, NULL);
   1.433 -	primitiveArray[0] = r[0];  // eax
   1.434 -	primitiveArray[1] = r[2];  // ecx
   1.435 -	primitiveArray[2] = r[3];  // edx
   1.436 -	primitiveArray[3] = r[1];  // ebx
   1.437 -	primitiveArray[4] = r[7];  // esp
   1.438 -	primitiveArray[5] = r[6];  // ebp
   1.439 -	primitiveArray[6] = r[5];  // esi
   1.440 -	primitiveArray[7] = r[4];  // edi
   1.441 -	(*env)->ReleaseLongArrayElements(env, registerArray, primitiveArray, 0);
   1.442 -#elif defined(__x86_64__)
   1.443 -	/* From AMD64ThreadContext.java
   1.444 -	   public static final int R15 = 0;
   1.445 -	   public static final int R14 = 1;
   1.446 -	   public static final int R13 = 2;
   1.447 -	   public static final int R12 = 3;
   1.448 -	   public static final int R11 = 4;
   1.449 -	   public static final int R10 = 5;
   1.450 -	   public static final int R9  = 6;
   1.451 -	   public static final int R8  = 7;
   1.452 -	   public static final int RDI = 8;
   1.453 -	   public static final int RSI = 9;
   1.454 -	   public static final int RBP = 10;
   1.455 -	   public static final int RBX = 11;
   1.456 -	   public static final int RDX = 12;
   1.457 -	   public static final int RCX = 13;
   1.458 -	   public static final int RAX = 14;
   1.459 -	   public static final int TRAPNO = 15;
   1.460 -	   public static final int ERR = 16;
   1.461 -	   public static final int RIP = 17;
   1.462 -	   public static final int CS = 18;
   1.463 -	   public static final int RFL = 19;
   1.464 -	   public static final int RSP = 20;
   1.465 -	   public static final int SS = 21;
   1.466 -	   public static final int FS = 22;
   1.467 -	   public static final int GS = 23;
   1.468 -	   public static final int ES = 24;
   1.469 -	   public static final int DS = 25;
   1.470 -	   public static final int FSBASE = 26;
   1.471 -	   public static final int GSBASE = 27;
   1.472 -	 */
   1.473 -	// 64 bit
   1.474 -	if (debug) printf("Getting threads for a 64-bit process\n");
   1.475 -	registerArray = (*env)->NewLongArray(env, 28);
   1.476 -	primitiveArray = (*env)->GetLongArrayElements(env, registerArray, NULL);
   1.477 +#if amd64
   1.478 +#define NPRGREG sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_NPRGREG
   1.479 +#undef REG_INDEX
   1.480 +#define REG_INDEX(reg) sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_##reg
   1.481  
   1.482 -	primitiveArray[0] = state.__r15;
   1.483 -	primitiveArray[1] = state.__r14;
   1.484 -	primitiveArray[2] = state.__r13;
   1.485 -	primitiveArray[3] = state.__r12;
   1.486 -	primitiveArray[4] = state.__r11;
   1.487 -	primitiveArray[5] = state.__r10;
   1.488 -	primitiveArray[6] = state.__r9;
   1.489 -	primitiveArray[7] = state.__r8;
   1.490 -	primitiveArray[8] = state.__rdi;
   1.491 -	primitiveArray[9] = state.__rsi;
   1.492 -	primitiveArray[10] = state.__rbp;
   1.493 -	primitiveArray[11] = state.__rbx;
   1.494 -	primitiveArray[12] = state.__rdx;
   1.495 -	primitiveArray[13] = state.__rcx;
   1.496 -	primitiveArray[14] = state.__rax;
   1.497 -	primitiveArray[15] = 0;             // trapno ?
   1.498 -	primitiveArray[16] = 0;             // err ?
   1.499 -	primitiveArray[17] = state.__rip;
   1.500 -	primitiveArray[18] = state.__cs;
   1.501 -	primitiveArray[19] = state.__rflags;
   1.502 -	primitiveArray[20] = state.__rsp;
   1.503 -	primitiveArray[21] = 0;            // We don't have SS
   1.504 -	primitiveArray[22] = state.__fs;
   1.505 -	primitiveArray[23] = state.__gs;
   1.506 -	primitiveArray[24] = 0;
   1.507 -	primitiveArray[25] = 0;
   1.508 -	primitiveArray[26] = 0;
   1.509 -	primitiveArray[27] = 0;
   1.510 +  // 64 bit
   1.511 +  print_debug("Getting threads for a 64-bit process\n");
   1.512 +  registerArray = (*env)->NewLongArray(env, NPRGREG);
   1.513 +  CHECK_EXCEPTION_(0);
   1.514 +  primitiveArray = (*env)->GetLongArrayElements(env, registerArray, NULL);
   1.515  
   1.516 -	if (debug) printf("set registers\n");
   1.517 +  primitiveArray[REG_INDEX(R15)] = state.__r15;
   1.518 +  primitiveArray[REG_INDEX(R14)] = state.__r14;
   1.519 +  primitiveArray[REG_INDEX(R13)] = state.__r13;
   1.520 +  primitiveArray[REG_INDEX(R12)] = state.__r12;
   1.521 +  primitiveArray[REG_INDEX(R11)] = state.__r11;
   1.522 +  primitiveArray[REG_INDEX(R10)] = state.__r10;
   1.523 +  primitiveArray[REG_INDEX(R9)]  = state.__r9;
   1.524 +  primitiveArray[REG_INDEX(R8)]  = state.__r8;
   1.525 +  primitiveArray[REG_INDEX(RDI)] = state.__rdi;
   1.526 +  primitiveArray[REG_INDEX(RSI)] = state.__rsi;
   1.527 +  primitiveArray[REG_INDEX(RBP)] = state.__rbp;
   1.528 +  primitiveArray[REG_INDEX(RBX)] = state.__rbx;
   1.529 +  primitiveArray[REG_INDEX(RDX)] = state.__rdx;
   1.530 +  primitiveArray[REG_INDEX(RCX)] = state.__rcx;
   1.531 +  primitiveArray[REG_INDEX(RAX)] = state.__rax;
   1.532 +  primitiveArray[REG_INDEX(TRAPNO)] = 0;            // trapno, not used
   1.533 +  primitiveArray[REG_INDEX(ERR)]    = 0;            // err, not used 
   1.534 +  primitiveArray[REG_INDEX(RIP)] = state.__rip;
   1.535 +  primitiveArray[REG_INDEX(CS)]  = state.__cs;
   1.536 +  primitiveArray[REG_INDEX(RFL)] = state.__rflags;
   1.537 +  primitiveArray[REG_INDEX(RSP)] = state.__rsp;
   1.538 +  primitiveArray[REG_INDEX(SS)] = 0;                // We don't have SS
   1.539 +  primitiveArray[REG_INDEX(FS)] = state.__fs;
   1.540 +  primitiveArray[REG_INDEX(GS)] = state.__gs;
   1.541 +  primitiveArray[REG_INDEX(ES)] = 0;
   1.542 +  primitiveArray[REG_INDEX(DS)] = 0;
   1.543 +  primitiveArray[REG_INDEX(FSBASE)] = 0;
   1.544 +  primitiveArray[REG_INDEX(GSBASE)] = 0;
   1.545 +  print_debug("set registers\n");
   1.546  
   1.547 -	(*env)->ReleaseLongArrayElements(env, registerArray, primitiveArray, 0);
   1.548 +  (*env)->ReleaseLongArrayElements(env, registerArray, primitiveArray, 0);
   1.549 +
   1.550  #else
   1.551 -#error Unsupported architecture
   1.552 -#endif
   1.553 +#error UNSUPPORTED_ARCH
   1.554 +#endif /* amd64 */
   1.555  
   1.556    return registerArray;
   1.557  }
   1.558 @@ -410,8 +601,7 @@
   1.559  Java_sun_jvm_hotspot_debugger_macosx_MacOSXDebuggerLocal_translateTID0(
   1.560    JNIEnv *env, jobject this_obj, jint tid) 
   1.561  {
   1.562 -  if (debug)
   1.563 -    printf("translateTID0 called on tid = 0x%x\n", (int)tid);
   1.564 +  print_debug("translateTID0 called on tid = 0x%x\n", (int)tid);
   1.565  
   1.566    kern_return_t result;
   1.567    thread_t foreign_tid, usable_tid;
   1.568 @@ -426,8 +616,7 @@
   1.569    if (result != KERN_SUCCESS)
   1.570      return -1;
   1.571      
   1.572 -  if (debug)
   1.573 -    printf("translateTID0: 0x%x -> 0x%x\n", foreign_tid, usable_tid);
   1.574 +  print_debug("translateTID0: 0x%x -> 0x%x\n", foreign_tid, usable_tid);
   1.575      
   1.576    return (jint) usable_tid;
   1.577  }
   1.578 @@ -437,7 +626,7 @@
   1.579    // pass the signal to the process so we don't swallow it
   1.580    int res;
   1.581    if ((res = ptrace(PT_CONTINUE, pid, (caddr_t)1, signal)) < 0) {
   1.582 -    fprintf(stderr, "attach: ptrace(PT_CONTINUE, %d) failed with %d\n", pid, res);
   1.583 +    print_error("attach: ptrace(PT_CONTINUE, %d) failed with %d\n", pid, res);
   1.584      return false;
   1.585    }
   1.586    return true;
   1.587 @@ -461,11 +650,11 @@
   1.588            return true;
   1.589          }
   1.590          if (!ptrace_continue(pid, WSTOPSIG(status))) {
   1.591 -          fprintf(stderr, "attach: Failed to correctly attach to VM. VM might HANG! [PTRACE_CONT failed, stopped by %d]\n", WSTOPSIG(status));
   1.592 +          print_error("attach: Failed to correctly attach to VM. VM might HANG! [PTRACE_CONT failed, stopped by %d]\n", WSTOPSIG(status));
   1.593            return false;
   1.594          }
   1.595        } else {
   1.596 -        fprintf(stderr, "attach: waitpid(): Child process exited/terminated (status = 0x%x)\n", status);
   1.597 +        print_error("attach: waitpid(): Child process exited/terminated (status = 0x%x)\n", status);
   1.598          return false;
   1.599        }
   1.600      } else {
   1.601 @@ -474,13 +663,13 @@
   1.602            continue;
   1.603            break;
   1.604          case ECHILD:
   1.605 -          fprintf(stderr, "attach: waitpid() failed. Child process pid (%d) does not exist \n", pid);
   1.606 +          print_error("attach: waitpid() failed. Child process pid (%d) does not exist \n", pid);
   1.607            break;
   1.608          case EINVAL:
   1.609 -          fprintf(stderr, "attach: waitpid() failed. Invalid options argument.\n");
   1.610 +          print_error("attach: waitpid() failed. Invalid options argument.\n");
   1.611            break;
   1.612          default:
   1.613 -          fprintf(stderr, "attach: waitpid() failed. Unexpected error %d\n",errno);
   1.614 +          print_error("attach: waitpid() failed. Unexpected error %d\n",errno);
   1.615            break;
   1.616        }
   1.617        return false;
   1.618 @@ -492,7 +681,7 @@
   1.619  static bool ptrace_attach(pid_t pid) {
   1.620    int res;
   1.621    if ((res = ptrace(PT_ATTACH, pid, 0, 0)) < 0) {
   1.622 -    fprintf(stderr, "ptrace(PT_ATTACH, %d) failed with %d\n", pid, res);
   1.623 +    print_error("ptrace(PT_ATTACH, %d) failed with %d\n", pid, res);
   1.624      return false;
   1.625    } else {
   1.626      return ptrace_waitpid(pid);
   1.627 @@ -504,23 +693,19 @@
   1.628   * Method:    attach0
   1.629   * Signature: (I)V
   1.630   */
   1.631 -JNIEXPORT void JNICALL 
   1.632 +JNIEXPORT void JNICALL
   1.633  Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_attach0__I(
   1.634 -  JNIEnv *env, jobject this_obj, jint jpid) 
   1.635 +  JNIEnv *env, jobject this_obj, jint jpid)
   1.636  {
   1.637 +  print_debug("attach0 called for jpid=%d\n", (int)jpid);
   1.638 +
   1.639  JNF_COCOA_ENTER(env);
   1.640 -  if (getenv("JAVA_SAPROC_DEBUG") != NULL)
   1.641 -    debug = JNI_TRUE;
   1.642 -  else
   1.643 -    debug = JNI_FALSE;
   1.644 -  if (debug) printf("attach0 called for jpid=%d\n", (int)jpid);
   1.645 -  
   1.646 -  // get the task from the pid
   1.647 +
   1.648    kern_return_t result;
   1.649    task_t gTask = 0;
   1.650    result = task_for_pid(mach_task_self(), jpid, &gTask);
   1.651    if (result != KERN_SUCCESS) {
   1.652 -    fprintf(stderr, "attach: task_for_pid(%d) failed (%d)\n", (int)jpid, result);
   1.653 +    print_error("attach: task_for_pid(%d) failed (%d)\n", (int)jpid, result);
   1.654      THROW_NEW_DEBUGGER_EXCEPTION("Can't attach to the process");
   1.655    }
   1.656    putTask(env, this_obj, gTask);
   1.657 @@ -550,18 +735,79 @@
   1.658  JNF_COCOA_EXIT(env);
   1.659  }
   1.660  
   1.661 +/** For core file, 
   1.662 +    called from Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_attach0__Ljava_lang_String_2Ljava_lang_String_2 */
   1.663 +static void fillLoadObjects(JNIEnv* env, jobject this_obj, struct ps_prochandle* ph) {
   1.664 +  int n = 0, i = 0;
   1.665 +
   1.666 +  // add load objects
   1.667 +  n = get_num_libs(ph);
   1.668 +  for (i = 0; i < n; i++) {
   1.669 +     uintptr_t base;
   1.670 +     const char* name;
   1.671 +     jobject loadObject;
   1.672 +     jobject loadObjectList;
   1.673 +
   1.674 +     base = get_lib_base(ph, i);
   1.675 +     name = get_lib_name(ph, i);
   1.676 +     loadObject = (*env)->CallObjectMethod(env, this_obj, createLoadObject_ID,
   1.677 +                                   (*env)->NewStringUTF(env, name), (jlong)0, (jlong)base);
   1.678 +     CHECK_EXCEPTION;
   1.679 +     loadObjectList = (*env)->GetObjectField(env, this_obj, loadObjectList_ID);
   1.680 +     CHECK_EXCEPTION;
   1.681 +     (*env)->CallBooleanMethod(env, loadObjectList, listAdd_ID, loadObject);
   1.682 +     CHECK_EXCEPTION;
   1.683 +  }
   1.684 +}
   1.685 +
   1.686 +/*
   1.687 + * Class:     sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
   1.688 + * Method:    attach0
   1.689 + * Signature: (Ljava/lang/String;Ljava/lang/String;)V
   1.690 + */
   1.691 +JNIEXPORT void JNICALL
   1.692 +Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_attach0__Ljava_lang_String_2Ljava_lang_String_2(
   1.693 +  JNIEnv *env, jobject this_obj, jstring execName, jstring coreName)
   1.694 +{
   1.695 +  const char *execName_cstr;
   1.696 +  const char *coreName_cstr;
   1.697 +  jboolean isCopy;
   1.698 +  struct ps_prochandle* ph;
   1.699 +
   1.700 +  execName_cstr = (*env)->GetStringUTFChars(env, execName, &isCopy);
   1.701 +  CHECK_EXCEPTION;
   1.702 +  coreName_cstr = (*env)->GetStringUTFChars(env, coreName, &isCopy);
   1.703 +  CHECK_EXCEPTION;
   1.704 +
   1.705 +  print_debug("attach: %s %s\n", execName_cstr, coreName_cstr);
   1.706 +
   1.707 +  if ( (ph = Pgrab_core(execName_cstr, coreName_cstr)) == NULL) {
   1.708 +    (*env)->ReleaseStringUTFChars(env, execName, execName_cstr);
   1.709 +    (*env)->ReleaseStringUTFChars(env, coreName, coreName_cstr);
   1.710 +    THROW_NEW_DEBUGGER_EXCEPTION("Can't attach to the core file");
   1.711 +  }
   1.712 +  (*env)->SetLongField(env, this_obj, p_ps_prochandle_ID, (jlong)(intptr_t)ph);
   1.713 +  (*env)->ReleaseStringUTFChars(env, execName, execName_cstr);
   1.714 +  (*env)->ReleaseStringUTFChars(env, coreName, coreName_cstr);
   1.715 +  fillLoadObjects(env, this_obj, ph);
   1.716 +}
   1.717 +
   1.718  /*
   1.719   * Class:     sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
   1.720   * Method:    detach0
   1.721   * Signature: ()V
   1.722   */
   1.723 -JNIEXPORT void JNICALL 
   1.724 +JNIEXPORT void JNICALL
   1.725  Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_detach0(
   1.726 -  JNIEnv *env, jobject this_obj) 
   1.727 +  JNIEnv *env, jobject this_obj)
   1.728  {
   1.729 +  print_debug("detach0 called\n");
   1.730 +  struct ps_prochandle* ph = get_proc_handle(env, this_obj);
   1.731 +  if (ph != NULL && ph->core != NULL) {
   1.732 +     Prelease(ph);
   1.733 +     return;
   1.734 +  }
   1.735  JNF_COCOA_ENTER(env);
   1.736 -  if (debug) printf("detach0 called\n");
   1.737 -
   1.738    task_t gTask = getTask(env, this_obj);
   1.739  
   1.740    // detach from the ptraced process causing it to resume execution
   1.741 @@ -569,15 +815,15 @@
   1.742    kern_return_t k_res;
   1.743    k_res = pid_for_task(gTask, &pid);
   1.744    if (k_res != KERN_SUCCESS) {
   1.745 -    fprintf(stderr, "detach: pid_for_task(%d) failed (%d)\n", pid, k_res);
   1.746 +    print_error("detach: pid_for_task(%d) failed (%d)\n", pid, k_res);
   1.747    }
   1.748    else {
   1.749      int res = ptrace(PT_DETACH, pid, 0, 0);
   1.750      if (res < 0) {
   1.751 -      fprintf(stderr, "detach: ptrace(PT_DETACH, %d) failed (%d)\n", pid, res);
   1.752 +      print_error("detach: ptrace(PT_DETACH, %d) failed (%d)\n", pid, res);
   1.753      }
   1.754    }
   1.755 -  
   1.756 +
   1.757    mach_port_deallocate(mach_task_self(), gTask);
   1.758    id symbolicator = getSymbolicator(env, this_obj);
   1.759    if (symbolicator != nil) {
   1.760 @@ -585,170 +831,3 @@
   1.761    }
   1.762  JNF_COCOA_EXIT(env);
   1.763  }
   1.764 -
   1.765 -/*
   1.766 - * Class:     sun_jvm_hotspot_asm_Disassembler
   1.767 - * Method:    load_library
   1.768 - * Signature: (Ljava/lang/String;)L
   1.769 - */
   1.770 -JNIEXPORT jlong JNICALL
   1.771 -Java_sun_jvm_hotspot_asm_Disassembler_load_1library(
   1.772 -  JNIEnv * env, 
   1.773 -  jclass disclass,
   1.774 -  jstring jrepath_s,
   1.775 -  jstring libname_s) 
   1.776 -{
   1.777 -  uintptr_t func = 0;
   1.778 -  const char* error_message = NULL;
   1.779 -  const char* java_home;
   1.780 -  jboolean isCopy;
   1.781 -  uintptr_t *handle = NULL;
   1.782 -
   1.783 -  const char * jrepath = (*env)->GetStringUTFChars(env, jrepath_s, &isCopy); // like $JAVA_HOME/jre/lib/sparc/
   1.784 -  const char * libname = (*env)->GetStringUTFChars(env, libname_s, &isCopy);
   1.785 -  char buffer[128];
   1.786 -
   1.787 -  /* Load the hsdis library */
   1.788 -  void* hsdis_handle;
   1.789 -  hsdis_handle = dlopen(libname, RTLD_LAZY | RTLD_GLOBAL);
   1.790 -  if (hsdis_handle == NULL) {
   1.791 -    snprintf(buffer, sizeof(buffer), "%s%s", jrepath, libname);
   1.792 -    hsdis_handle = dlopen(buffer, RTLD_LAZY | RTLD_GLOBAL);
   1.793 -  }
   1.794 -  if (hsdis_handle != NULL) {
   1.795 -    func = (uintptr_t)dlsym(hsdis_handle, "decode_instructions_virtual");
   1.796 -  }
   1.797 -  if (func == 0) {
   1.798 -    error_message = dlerror();
   1.799 -    fprintf(stderr, "%s\n", error_message);
   1.800 -  }
   1.801 -
   1.802 -  (*env)->ReleaseStringUTFChars(env, libname_s, libname);
   1.803 -  (*env)->ReleaseStringUTFChars(env, jrepath_s, jrepath);
   1.804 -
   1.805 -  if (func == 0) {
   1.806 -    /* Couldn't find entry point.  error_message should contain some
   1.807 -     * platform dependent error message.
   1.808 -     */
   1.809 -    THROW_NEW_DEBUGGER_EXCEPTION_(error_message, (jlong)func);
   1.810 -  }
   1.811 -  return (jlong)func;
   1.812 -}
   1.813 -
   1.814 -/* signature of decode_instructions_virtual from hsdis.h */
   1.815 -typedef void* (*decode_func)(uintptr_t start_va, uintptr_t end_va,
   1.816 -                             unsigned char* start, uintptr_t length,
   1.817 -                             void* (*event_callback)(void*, const char*, void*),
   1.818 -                             void* event_stream,
   1.819 -                             int (*printf_callback)(void*, const char*, ...),
   1.820 -                             void* printf_stream,
   1.821 -                             const char* options);
   1.822 -
   1.823 -/* container for call back state when decoding instructions */
   1.824 -typedef struct {
   1.825 -  JNIEnv* env;
   1.826 -  jobject dis;
   1.827 -  jobject visitor;
   1.828 -  jmethodID handle_event;
   1.829 -  jmethodID raw_print;
   1.830 -  char buffer[4096];
   1.831 -} decode_env;
   1.832 -
   1.833 -
   1.834 -/* event callback binding to Disassembler.handleEvent */
   1.835 -static void* event_to_env(void* env_pv, const char* event, void* arg) {
   1.836 -  decode_env* denv = (decode_env*)env_pv;
   1.837 -  JNIEnv* env = denv->env;
   1.838 -  jstring event_string = (*env)->NewStringUTF(env, event);
   1.839 -  jlong result = (*env)->CallLongMethod(env, denv->dis, denv->handle_event, denv->visitor,
   1.840 -                                        event_string, (jlong) (uintptr_t)arg);
   1.841 -  /* ignore exceptions for now */
   1.842 -  CHECK_EXCEPTION_CLEAR_((void *)0);
   1.843 -  return (void*)(uintptr_t)result;
   1.844 -}
   1.845 -
   1.846 -/* printing callback binding to Disassembler.rawPrint */
   1.847 -static int printf_to_env(void* env_pv, const char* format, ...) {
   1.848 -  jstring output;
   1.849 -  va_list ap;
   1.850 -  int cnt;
   1.851 -  decode_env* denv = (decode_env*)env_pv;
   1.852 -  JNIEnv* env = denv->env;
   1.853 -  size_t flen = strlen(format);
   1.854 -  const char* raw = NULL;
   1.855 -
   1.856 -  if (flen == 0)  return 0;
   1.857 -  if (flen < 2 ||
   1.858 -      strchr(format, '%') == NULL) {
   1.859 -    raw = format;
   1.860 -  } else if (format[0] == '%' && format[1] == '%' &&
   1.861 -             strchr(format+2, '%') == NULL) {
   1.862 -    // happens a lot on machines with names like %foo
   1.863 -    flen--;
   1.864 -    raw = format+1;
   1.865 -  }
   1.866 -  if (raw != NULL) {
   1.867 -    jstring output = (*env)->NewStringUTF(env, raw);
   1.868 -    (*env)->CallVoidMethod(env, denv->dis, denv->raw_print, denv->visitor, output);
   1.869 -    CHECK_EXCEPTION_CLEAR;
   1.870 -    return (int) flen;
   1.871 -  }
   1.872 -  va_start(ap, format);
   1.873 -  cnt = vsnprintf(denv->buffer, sizeof(denv->buffer), format, ap);
   1.874 -  va_end(ap);
   1.875 -
   1.876 -  output = (*env)->NewStringUTF(env, denv->buffer);
   1.877 -  (*env)->CallVoidMethod(env, denv->dis, denv->raw_print, denv->visitor, output);
   1.878 -  CHECK_EXCEPTION_CLEAR;
   1.879 -  return cnt;
   1.880 -}
   1.881 -
   1.882 -/*
   1.883 - * Class:     sun_jvm_hotspot_asm_Disassembler
   1.884 - * Method:    decode
   1.885 - * Signature: (Lsun/jvm/hotspot/asm/InstructionVisitor;J[BLjava/lang/String;J)V
   1.886 - */
   1.887 -JNIEXPORT void JNICALL
   1.888 -Java_sun_jvm_hotspot_asm_Disassembler_decode(
   1.889 -   JNIEnv * env,
   1.890 -   jobject dis,
   1.891 -   jobject visitor,
   1.892 -   jlong startPc,
   1.893 -   jbyteArray code,
   1.894 -   jstring options_s,
   1.895 -   jlong decode_instructions_virtual) 
   1.896 -{
   1.897 -  jboolean isCopy;
   1.898 -  jbyte* start = (*env)->GetByteArrayElements(env, code, &isCopy);
   1.899 -  jbyte* end = start + (*env)->GetArrayLength(env, code);
   1.900 -  const char * options = (*env)->GetStringUTFChars(env, options_s, &isCopy);
   1.901 -  jclass disclass = (*env)->GetObjectClass(env, dis);
   1.902 -
   1.903 -  decode_env denv;
   1.904 -  denv.env = env;
   1.905 -  denv.dis = dis;
   1.906 -  denv.visitor = visitor;
   1.907 -
   1.908 -  /* find Disassembler.handleEvent callback */
   1.909 -  denv.handle_event = (*env)->GetMethodID(env, disclass, "handleEvent",
   1.910 -                                          "(Lsun/jvm/hotspot/asm/InstructionVisitor;Ljava/lang/String;J)J");
   1.911 -  CHECK_EXCEPTION_CLEAR_VOID
   1.912 -
   1.913 -  /* find Disassembler.rawPrint callback */
   1.914 -  denv.raw_print = (*env)->GetMethodID(env, disclass, "rawPrint",
   1.915 -                                       "(Lsun/jvm/hotspot/asm/InstructionVisitor;Ljava/lang/String;)V");
   1.916 -  CHECK_EXCEPTION_CLEAR_VOID
   1.917 -
   1.918 -  /* decode the buffer */
   1.919 -  (*(decode_func)(uintptr_t)decode_instructions_virtual)(startPc,
   1.920 -                                                         startPc + end - start,
   1.921 -                                                         (unsigned char*)start,
   1.922 -                                                         end - start,
   1.923 -                                                         &event_to_env,  (void*) &denv,
   1.924 -                                                         &printf_to_env, (void*) &denv,
   1.925 -                                                         options);
   1.926 -
   1.927 -  /* cleanup */
   1.928 -  (*env)->ReleaseByteArrayElements(env, code, start, JNI_ABORT);
   1.929 -  (*env)->ReleaseStringUTFChars(env, options_s, options);
   1.930 -}
     2.1 --- a/agent/src/os/bsd/Makefile	Fri Mar 15 11:44:33 2013 -0700
     2.2 +++ b/agent/src/os/bsd/Makefile	Sun Mar 17 08:57:56 2013 -0700
     2.3 @@ -1,5 +1,5 @@
     2.4  #
     2.5 -# Copyright (c) 2002, 2009, Oracle and/or its affiliates. All rights reserved.
     2.6 +# Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
     2.7  # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     2.8  #
     2.9  # This code is free software; you can redistribute it and/or modify it
    2.10 @@ -22,34 +22,60 @@
    2.11  #  
    2.12  #
    2.13  
    2.14 -ARCH := $(shell if ([ `uname -m` = "ia64" ])  ; then echo ia64 ; elif ([ `uname -m` = "amd64" ]) ; then echo amd64; elif ([ `uname -m` = "sparc64" ]) ; then echo sparc; else echo i386 ; fi )
    2.15 +ARCH := $(shell if ([ `uname -m` = "ia64" ])  ; then echo ia64 ; elif ([ `uname -m` = "amd64" ]) ; then echo amd64; elif ([ `uname -m` = "x86_64" ]) ; then echo amd64; elif ([ `uname -m` = "sparc64" ]) ; then echo sparc; else echo i386 ; fi )
    2.16 +
    2.17 +OS       := $(shell uname -s)
    2.18 +
    2.19  GCC      = gcc
    2.20  
    2.21  JAVAH    = ${JAVA_HOME}/bin/javah
    2.22  
    2.23 +ifneq ($(OS), Darwin)
    2.24  SOURCES  = salibelf.c   \
    2.25          symtab.c        \
    2.26  	libproc_impl.c  \
    2.27  	ps_proc.c       \
    2.28  	ps_core.c       \
    2.29  	BsdDebuggerLocal.c
    2.30 -
    2.31 -INCLUDES = -I${JAVA_HOME}/include -I${JAVA_HOME}/include/$(shell uname -s | tr "[:upper:]" "[:lower:]")
    2.32 -
    2.33 -OBJS     = $(SOURCES:.c=.o)
    2.34 +OBJS    = $(SOURCES:.c=.o)
    2.35 +OBJSPLUS = $(OBJS) sadis.o
    2.36 +LIBSA = $(ARCH)/libsaproc.so
    2.37  
    2.38  LIBS     = -lutil -lthread_db
    2.39  
    2.40 -CFLAGS   = -c -fPIC -g -Wall -D_ALLBSD_SOURCE -D_GNU_SOURCE -D$(ARCH) $(INCLUDES)
    2.41 +else
    2.42  
    2.43 -LIBSA = $(ARCH)/libsaproc.so
    2.44 +SOURCES  = symtab.c     \
    2.45 +	libproc_impl.c  \
    2.46 +	ps_core.c
    2.47 +OBJS    = $(SOURCES:.c=.o)
    2.48 +OBJSPLUS = MacosxDebuggerLocal.o sadis.o $(OBJS)
    2.49 +EXTINCLUDE = -I/System/Library/Frameworks/JavaVM.framework/Headers -I.
    2.50 +EXTCFLAGS = -m64 -D__APPLE__ -framework JavaNativeFoundation
    2.51 +FOUNDATIONFLAGS = -framework Foundation -F/System/Library/Frameworks/JavaVM.framework/Frameworks -framework JavaNativeFoundation -framework Security -framework CoreFoundation
    2.52 +LIBSA = $(ARCH)/libsaproc.dylib
    2.53 +endif   # Darwin
    2.54 +
    2.55 +INCLUDES = -I${JAVA_HOME}/include -I${JAVA_HOME}/include/$(shell uname -s | tr "[:upper:]" "[:lower:]") $(EXTINCLUDE)
    2.56 +
    2.57 +
    2.58 +
    2.59 +CFLAGS   = -c -fPIC -g -Wall -D_ALLBSD_SOURCE -D_GNU_SOURCE -D$(ARCH) $(INCLUDES) $(EXTCFLAGS)
    2.60 +
    2.61 +
    2.62  
    2.63  all: $(LIBSA)
    2.64  
    2.65 -BsdDebuggerLocal.o: BsdDebuggerLocal.c
    2.66 -	$(JAVAH) -jni -classpath ../../../../../build/bsd-i586/hotspot/outputdir/bsd_i486_compiler2/generated/saclasses  \
    2.67 +MacosxDebuggerLocal.o: MacosxDebuggerLocal.m
    2.68 +	echo "OS="$(OS)
    2.69 +	$(JAVAH) -jni -classpath ../../../build/classes  \
    2.70  		sun.jvm.hotspot.debugger.x86.X86ThreadContext \
    2.71  		sun.jvm.hotspot.debugger.amd64.AMD64ThreadContext
    2.72 +	$(GCC) $(CFLAGS) $(FOUNDATIONFLAGS) $<
    2.73 +
    2.74 +sadis.o: ../../share/native/sadis.c
    2.75 +	$(JAVAH) -jni -classpath ../../../build/classes \
    2.76 +		sun.jvm.hotspot.asm.Disassembler
    2.77  	$(GCC) $(CFLAGS) $<
    2.78  
    2.79  .c.obj:
    2.80 @@ -59,9 +85,9 @@
    2.81    LFLAGS_LIBSA = -Xlinker --version-script=mapfile
    2.82  endif
    2.83  
    2.84 -$(LIBSA): $(OBJS) mapfile
    2.85 +$(LIBSA): $(OBJSPLUS) mapfile 
    2.86  	if [ ! -d $(ARCH) ] ; then mkdir $(ARCH) ; fi
    2.87 -	$(GCC) -shared $(LFLAGS_LIBSA) -o $(LIBSA) $(OBJS) $(LIBS)
    2.88 +	$(GCC) -shared $(LFLAGS_LIBSA) -o $(LIBSA) $(FOUNDATIONFLAGS) $(OBJSPLUS) $(LIBS) $(SALIBS)
    2.89  
    2.90  test.o: $(LIBSA) test.c
    2.91  	$(GCC) -c -o test.o -g -D_GNU_SOURCE -D$(ARCH) $(INCLUDES) test.c
    2.92 @@ -71,7 +97,6 @@
    2.93  
    2.94  clean:
    2.95  	rm -f $(LIBSA)
    2.96 -	rm -f $(OBJS)
    2.97 +	rm -f *.o
    2.98  	rm -f test.o
    2.99  	-rmdir $(ARCH)
   2.100 -
     3.1 --- a/agent/src/os/bsd/libproc.h	Fri Mar 15 11:44:33 2013 -0700
     3.2 +++ b/agent/src/os/bsd/libproc.h	Sun Mar 17 08:57:56 2013 -0700
     3.3 @@ -1,5 +1,5 @@
     3.4  /*
     3.5 - * Copyright (c) 2003, 2007, Oracle and/or its affiliates. All rights reserved.
     3.6 + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
     3.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3.8   *
     3.9   * This code is free software; you can redistribute it and/or modify it
    3.10 @@ -27,9 +27,38 @@
    3.11  
    3.12  #include <unistd.h>
    3.13  #include <stdint.h>
    3.14 +#include <stdarg.h>
    3.15 +#include <stdio.h>
    3.16 +#include <stdlib.h>
    3.17 +#include <string.h>
    3.18 +#include <fcntl.h>
    3.19 +
    3.20 +#ifdef __APPLE__
    3.21 +typedef enum ps_err_e {
    3.22 +  PS_OK, PS_ERR, PS_BADPID, PS_BADLID,
    3.23 +  PS_BADADDR, PS_NOSYM, PS_NOFREGS
    3.24 +} ps_err_e;
    3.25 +
    3.26 +#ifndef psaddr_t
    3.27 +#define psaddr_t uintptr_t
    3.28 +#endif
    3.29 +
    3.30 +#ifndef bool
    3.31 +typedef int bool;
    3.32 +#define true  1
    3.33 +#define false 0
    3.34 +#endif  // bool
    3.35 +
    3.36 +#ifndef lwpid_t
    3.37 +#define lwpid_t uintptr_t
    3.38 +#endif
    3.39 +
    3.40 +#include <mach/thread_status.h>
    3.41 +#else   // __APPLE__
    3.42 +#include <elf.h>
    3.43 +#include <link.h>
    3.44  #include <machine/reg.h>
    3.45  #include <proc_service.h>
    3.46 -
    3.47  #if defined(sparc) || defined(sparcv9)
    3.48  /*
    3.49    If _LP64 is defined ptrace.h should be taken from /usr/include/asm-sparc64
    3.50 @@ -44,6 +73,14 @@
    3.51  
    3.52  #endif //sparc or sparcv9
    3.53  
    3.54 +// This C bool type must be int for compatibility with BSD calls and
    3.55 +// it would be a mistake to equivalence it to C++ bool on many platforms
    3.56 +typedef int bool;
    3.57 +#define true  1
    3.58 +#define false 0
    3.59 +
    3.60 +#endif // __APPLE__
    3.61 +
    3.62  /************************************************************************************
    3.63  
    3.64  0. This is very minimal subset of Solaris libproc just enough for current application.
    3.65 @@ -72,13 +109,7 @@
    3.66  
    3.67  *************************************************************************************/
    3.68  
    3.69 -// This C bool type must be int for compatibility with BSD calls and
    3.70 -// it would be a mistake to equivalence it to C++ bool on many platforms
    3.71 -
    3.72 -typedef int bool;
    3.73 -#define true  1
    3.74 -#define false 0
    3.75 -
    3.76 +struct reg;
    3.77  struct ps_prochandle;
    3.78  
    3.79  // attach to a process
     4.1 --- a/agent/src/os/bsd/libproc_impl.c	Fri Mar 15 11:44:33 2013 -0700
     4.2 +++ b/agent/src/os/bsd/libproc_impl.c	Sun Mar 17 08:57:56 2013 -0700
     4.3 @@ -21,12 +21,6 @@
     4.4   * questions.
     4.5   *
     4.6   */
     4.7 -#include <stdarg.h>
     4.8 -#include <stdio.h>
     4.9 -#include <stdlib.h>
    4.10 -#include <string.h>
    4.11 -#include <fcntl.h>
    4.12 -#include <thread_db.h>
    4.13  #include "libproc_impl.h"
    4.14  
    4.15  static const char* alt_root = NULL;
    4.16 @@ -34,61 +28,65 @@
    4.17  
    4.18  #define SA_ALTROOT "SA_ALTROOT"
    4.19  
    4.20 +off_t ltell(int fd) {
    4.21 +  return lseek(fd, 0, SEEK_CUR);
    4.22 +}
    4.23 +
    4.24  static void init_alt_root() {
    4.25 -   if (alt_root_len == -1) {
    4.26 -      alt_root = getenv(SA_ALTROOT);
    4.27 -      if (alt_root) {
    4.28 -         alt_root_len = strlen(alt_root);
    4.29 -      } else {
    4.30 -         alt_root_len = 0;
    4.31 -      }
    4.32 -   }
    4.33 +  if (alt_root_len == -1) {
    4.34 +    alt_root = getenv(SA_ALTROOT);
    4.35 +    if (alt_root) {
    4.36 +      alt_root_len = strlen(alt_root);
    4.37 +    } else {
    4.38 +      alt_root_len = 0;
    4.39 +    }
    4.40 +  }
    4.41  }
    4.42  
    4.43  int pathmap_open(const char* name) {
    4.44 -   int fd;
    4.45 -   char alt_path[PATH_MAX + 1];
    4.46 +  int fd;
    4.47 +  char alt_path[PATH_MAX + 1];
    4.48  
    4.49 -   init_alt_root();
    4.50 -   fd = open(name, O_RDONLY);
    4.51 -   if (fd >= 0) {
    4.52 +  init_alt_root();
    4.53 +
    4.54 +  if (alt_root_len > 0) {
    4.55 +    strcpy(alt_path, alt_root);
    4.56 +    strcat(alt_path, name);
    4.57 +    fd = open(alt_path, O_RDONLY);
    4.58 +    if (fd >= 0) {
    4.59 +      print_debug("path %s substituted for %s\n", alt_path, name);
    4.60        return fd;
    4.61 -   }
    4.62 +    }
    4.63  
    4.64 -   if (alt_root_len > 0) {
    4.65 +    if (strrchr(name, '/')) {
    4.66        strcpy(alt_path, alt_root);
    4.67 -      strcat(alt_path, name);
    4.68 +      strcat(alt_path, strrchr(name, '/'));
    4.69        fd = open(alt_path, O_RDONLY);
    4.70        if (fd >= 0) {
    4.71 -         print_debug("path %s substituted for %s\n", alt_path, name);
    4.72 -         return fd;
    4.73 +        print_debug("path %s substituted for %s\n", alt_path, name);
    4.74 +        return fd;
    4.75        }
    4.76 -
    4.77 -      if (strrchr(name, '/')) {
    4.78 -         strcpy(alt_path, alt_root);
    4.79 -         strcat(alt_path, strrchr(name, '/'));
    4.80 -         fd = open(alt_path, O_RDONLY);
    4.81 -         if (fd >= 0) {
    4.82 -            print_debug("path %s substituted for %s\n", alt_path, name);
    4.83 -            return fd;
    4.84 -         }
    4.85 -      }
    4.86 -   }
    4.87 -
    4.88 -   return -1;
    4.89 +    }
    4.90 +  } else {
    4.91 +    fd = open(name, O_RDONLY);
    4.92 +    if (fd >= 0) {
    4.93 +      return fd;
    4.94 +    }
    4.95 +  }
    4.96 +  return -1;
    4.97  }
    4.98  
    4.99  static bool _libsaproc_debug;
   4.100  
   4.101  void print_debug(const char* format,...) {
   4.102 -   if (_libsaproc_debug) {
   4.103 -     va_list alist;
   4.104 +  if (_libsaproc_debug) {
   4.105 +    va_list alist;
   4.106  
   4.107 -     va_start(alist, format);
   4.108 -     fputs("libsaproc DEBUG: ", stderr);
   4.109 -     vfprintf(stderr, format, alist);
   4.110 -     va_end(alist);
   4.111 -   }
   4.112 +    va_start(alist, format);
   4.113 +    fputs("libsaproc DEBUG: ", stderr);
   4.114 +    vfprintf(stderr, format, alist);
   4.115 +    va_end(alist);
   4.116 +  }
   4.117  }
   4.118  
   4.119  void print_error(const char* format,...) {
   4.120 @@ -100,172 +98,235 @@
   4.121  }
   4.122  
   4.123  bool is_debug() {
   4.124 -   return _libsaproc_debug;
   4.125 +  return _libsaproc_debug;
   4.126  }
   4.127  
   4.128 +#ifdef __APPLE__
   4.129 +// get arch offset in file
   4.130 +bool get_arch_off(int fd, cpu_type_t cputype, off_t *offset) {
   4.131 +  struct fat_header fatheader;
   4.132 +  struct fat_arch fatarch;
   4.133 +  off_t img_start = 0;
   4.134 +
   4.135 +  off_t pos = ltell(fd);
   4.136 +  if (read(fd, (void *)&fatheader, sizeof(struct fat_header)) != sizeof(struct fat_header)) {
   4.137 +    return false;
   4.138 +  }
   4.139 +  if (fatheader.magic == FAT_CIGAM) {
   4.140 +    int i;
   4.141 +    for (i = 0; i < ntohl(fatheader.nfat_arch); i++) {
   4.142 +      if (read(fd, (void *)&fatarch, sizeof(struct fat_arch)) != sizeof(struct fat_arch)) {
   4.143 +        return false;
   4.144 +      }
   4.145 +      if (ntohl(fatarch.cputype) == cputype) {
   4.146 +        print_debug("fat offset=%x\n", ntohl(fatarch.offset));
   4.147 +        img_start = ntohl(fatarch.offset);
   4.148 +        break;
   4.149 +      }
   4.150 +    }
   4.151 +    if (img_start == 0) {
   4.152 +      return false;
   4.153 +    }
   4.154 +  }
   4.155 +  lseek(fd, pos, SEEK_SET);
   4.156 +  *offset = img_start;
   4.157 +  return true;
   4.158 +}
   4.159 +
   4.160 +bool is_macho_file(int fd) {
   4.161 +  mach_header_64 fhdr;
   4.162 +  off_t x86_64_off;
   4.163 +
   4.164 +  if (fd < 0) {
   4.165 +    print_debug("Invalid file handle passed to is_macho_file\n");
   4.166 +    return false;
   4.167 +  }
   4.168 +
   4.169 +  off_t pos = ltell(fd);
   4.170 +  // check fat header
   4.171 +  if (!get_arch_off(fd, CPU_TYPE_X86_64, &x86_64_off)) {
   4.172 +    print_debug("failed to get fat header\n");
   4.173 +    return false;
   4.174 +  }
   4.175 +  lseek(fd, x86_64_off, SEEK_SET);
   4.176 +  if (read(fd, (void *)&fhdr, sizeof(mach_header_64)) != sizeof(mach_header_64)) {
   4.177 +     return false;
   4.178 +  }
   4.179 +  lseek(fd, pos, SEEK_SET);               // restore
   4.180 +  print_debug("fhdr.magic %x\n", fhdr.magic);
   4.181 +  return (fhdr.magic == MH_MAGIC_64 || fhdr.magic == MH_CIGAM_64);
   4.182 +}
   4.183 +
   4.184 +#endif //__APPLE__
   4.185 +
   4.186  // initialize libproc
   4.187  bool init_libproc(bool debug) {
   4.188 -   // init debug mode
   4.189     _libsaproc_debug = debug;
   4.190 -
   4.191 +#ifndef __APPLE__
   4.192     // initialize the thread_db library
   4.193     if (td_init() != TD_OK) {
   4.194       print_debug("libthread_db's td_init failed\n");
   4.195       return false;
   4.196     }
   4.197 -
   4.198 +#endif // __APPLE__
   4.199     return true;
   4.200  }
   4.201  
   4.202 -static void destroy_lib_info(struct ps_prochandle* ph) {
   4.203 -   lib_info* lib = ph->libs;
   4.204 -   while (lib) {
   4.205 -     lib_info *next = lib->next;
   4.206 -     if (lib->symtab) {
   4.207 -        destroy_symtab(lib->symtab);
   4.208 -     }
   4.209 -     free(lib);
   4.210 -     lib = next;
   4.211 -   }
   4.212 +void destroy_lib_info(struct ps_prochandle* ph) {
   4.213 +  lib_info* lib = ph->libs;
   4.214 +  while (lib) {
   4.215 +    lib_info* next = lib->next;
   4.216 +    if (lib->symtab) {
   4.217 +      destroy_symtab(lib->symtab);
   4.218 +    }
   4.219 +    free(lib);
   4.220 +    lib = next;
   4.221 +  }
   4.222  }
   4.223  
   4.224 -static void destroy_thread_info(struct ps_prochandle* ph) {
   4.225 -   thread_info* thr = ph->threads;
   4.226 -   while (thr) {
   4.227 -     thread_info *next = thr->next;
   4.228 -     free(thr);
   4.229 -     thr = next;
   4.230 -   }
   4.231 +void destroy_thread_info(struct ps_prochandle* ph) {
   4.232 +  sa_thread_info* thr = ph->threads;
   4.233 +  while (thr) {
   4.234 +    sa_thread_info* n = thr->next;
   4.235 +    free(thr);
   4.236 +    thr = n;
   4.237 +  }
   4.238  }
   4.239  
   4.240  // ps_prochandle cleanup
   4.241 -
   4.242 -// ps_prochandle cleanup
   4.243  void Prelease(struct ps_prochandle* ph) {
   4.244 -   // do the "derived class" clean-up first
   4.245 -   ph->ops->release(ph);
   4.246 -   destroy_lib_info(ph);
   4.247 -   destroy_thread_info(ph);
   4.248 -   free(ph);
   4.249 +  // do the "derived class" clean-up first
   4.250 +  ph->ops->release(ph);
   4.251 +  destroy_lib_info(ph);
   4.252 +  destroy_thread_info(ph);
   4.253 +  free(ph);
   4.254  }
   4.255  
   4.256  lib_info* add_lib_info(struct ps_prochandle* ph, const char* libname, uintptr_t base) {
   4.257 -   return add_lib_info_fd(ph, libname, -1, base);
   4.258 +  return add_lib_info_fd(ph, libname, -1, base);
   4.259  }
   4.260  
   4.261  lib_info* add_lib_info_fd(struct ps_prochandle* ph, const char* libname, int fd, uintptr_t base) {
   4.262     lib_info* newlib;
   4.263 +  print_debug("add_lib_info_fd %s\n", libname);
   4.264  
   4.265 -   if ( (newlib = (lib_info*) calloc(1, sizeof(struct lib_info))) == NULL) {
   4.266 -      print_debug("can't allocate memory for lib_info\n");
   4.267 -      return NULL;
   4.268 -   }
   4.269 +  if ( (newlib = (lib_info*) calloc(1, sizeof(struct lib_info))) == NULL) {
   4.270 +    print_debug("can't allocate memory for lib_info\n");
   4.271 +    return NULL;
   4.272 +  }
   4.273  
   4.274 -   strncpy(newlib->name, libname, sizeof(newlib->name));
   4.275 -   newlib->base = base;
   4.276 +  strncpy(newlib->name, libname, sizeof(newlib->name));
   4.277 +  newlib->base = base;
   4.278  
   4.279 -   if (fd == -1) {
   4.280 -      if ( (newlib->fd = pathmap_open(newlib->name)) < 0) {
   4.281 -         print_debug("can't open shared object %s\n", newlib->name);
   4.282 -         free(newlib);
   4.283 -         return NULL;
   4.284 -      }
   4.285 -   } else {
   4.286 -      newlib->fd = fd;
   4.287 -   }
   4.288 -
   4.289 -   // check whether we have got an ELF file. /proc/<pid>/map
   4.290 -   // gives out all file mappings and not just shared objects
   4.291 -   if (is_elf_file(newlib->fd) == false) {
   4.292 -      close(newlib->fd);
   4.293 +  if (fd == -1) {
   4.294 +    if ( (newlib->fd = pathmap_open(newlib->name)) < 0) {
   4.295 +      print_debug("can't open shared object %s\n", newlib->name);
   4.296        free(newlib);
   4.297        return NULL;
   4.298 -   }
   4.299 +    }
   4.300 +  } else {
   4.301 +    newlib->fd = fd;
   4.302 +  }
   4.303  
   4.304 -   newlib->symtab = build_symtab(newlib->fd);
   4.305 -   if (newlib->symtab == NULL) {
   4.306 -      print_debug("symbol table build failed for %s\n", newlib->name);
   4.307 -   }
   4.308 -   else {
   4.309 -      print_debug("built symbol table for %s\n", newlib->name);
   4.310 -   }
   4.311 +#ifdef __APPLE__
   4.312 +  // check whether we have got an Macho file.
   4.313 +  if (is_macho_file(newlib->fd) == false) {
   4.314 +    close(newlib->fd);
   4.315 +    free(newlib);
   4.316 +    print_debug("not a mach-o file\n");
   4.317 +    return NULL;
   4.318 +  }
   4.319 +#else
   4.320 +  // check whether we have got an ELF file. /proc/<pid>/map
   4.321 +  // gives out all file mappings and not just shared objects
   4.322 +  if (is_elf_file(newlib->fd) == false) {
   4.323 +    close(newlib->fd);
   4.324 +    free(newlib);
   4.325 +    return NULL;
   4.326 +  }
   4.327 +#endif // __APPLE__
   4.328  
   4.329 -   // even if symbol table building fails, we add the lib_info.
   4.330 -   // This is because we may need to read from the ELF file for core file
   4.331 -   // address read functionality. lookup_symbol checks for NULL symtab.
   4.332 -   if (ph->libs) {
   4.333 -      ph->lib_tail->next = newlib;
   4.334 -      ph->lib_tail = newlib;
   4.335 -   }  else {
   4.336 -      ph->libs = ph->lib_tail = newlib;
   4.337 -   }
   4.338 -   ph->num_libs++;
   4.339 +  newlib->symtab = build_symtab(newlib->fd);
   4.340 +  if (newlib->symtab == NULL) {
   4.341 +    print_debug("symbol table build failed for %s\n", newlib->name);
   4.342 +  } else {
   4.343 +    print_debug("built symbol table for %s\n", newlib->name);
   4.344 +  }
   4.345  
   4.346 -   return newlib;
   4.347 +  // even if symbol table building fails, we add the lib_info.
   4.348 +  // This is because we may need to read from the ELF file or MachO file for core file
   4.349 +  // address read functionality. lookup_symbol checks for NULL symtab.
   4.350 +  if (ph->libs) {
   4.351 +    ph->lib_tail->next = newlib;
   4.352 +    ph->lib_tail = newlib;
   4.353 +  }  else {
   4.354 +    ph->libs = ph->lib_tail = newlib;
   4.355 +  }
   4.356 +  ph->num_libs++;
   4.357 +  return newlib;
   4.358  }
   4.359  
   4.360  // lookup for a specific symbol
   4.361  uintptr_t lookup_symbol(struct ps_prochandle* ph,  const char* object_name,
   4.362                         const char* sym_name) {
   4.363 -   // ignore object_name. search in all libraries
   4.364 -   // FIXME: what should we do with object_name?? The library names are obtained
   4.365 -   // by parsing /proc/<pid>/maps, which may not be the same as object_name.
   4.366 -   // What we need is a utility to map object_name to real file name, something
   4.367 -   // dlopen() does by looking at LD_LIBRARY_PATH and /etc/ld.so.cache. For
   4.368 -   // now, we just ignore object_name and do a global search for the symbol.
   4.369 +  // ignore object_name. search in all libraries
   4.370 +  // FIXME: what should we do with object_name?? The library names are obtained
   4.371 +  // by parsing /proc/<pid>/maps, which may not be the same as object_name.
   4.372 +  // What we need is a utility to map object_name to real file name, something
   4.373 +  // dlopen() does by looking at LD_LIBRARY_PATH and /etc/ld.so.cache. For
   4.374 +  // now, we just ignore object_name and do a global search for the symbol.
   4.375  
   4.376 -   lib_info* lib = ph->libs;
   4.377 -   while (lib) {
   4.378 -      if (lib->symtab) {
   4.379 -         uintptr_t res = search_symbol(lib->symtab, lib->base, sym_name, NULL);
   4.380 -         if (res) return res;
   4.381 -      }
   4.382 -      lib = lib->next;
   4.383 -   }
   4.384 +  lib_info* lib = ph->libs;
   4.385 +  while (lib) {
   4.386 +    if (lib->symtab) {
   4.387 +      uintptr_t res = search_symbol(lib->symtab, lib->base, sym_name, NULL);
   4.388 +      if (res) return res;
   4.389 +    }
   4.390 +    lib = lib->next;
   4.391 +  }
   4.392  
   4.393 -   print_debug("lookup failed for symbol '%s' in obj '%s'\n",
   4.394 +  print_debug("lookup failed for symbol '%s' in obj '%s'\n",
   4.395                            sym_name, object_name);
   4.396 -   return (uintptr_t) NULL;
   4.397 +  return (uintptr_t) NULL;
   4.398  }
   4.399  
   4.400 -
   4.401  const char* symbol_for_pc(struct ps_prochandle* ph, uintptr_t addr, uintptr_t* poffset) {
   4.402 -   const char* res = NULL;
   4.403 -   lib_info* lib = ph->libs;
   4.404 -   while (lib) {
   4.405 -      if (lib->symtab && addr >= lib->base) {
   4.406 -         res = nearest_symbol(lib->symtab, addr - lib->base, poffset);
   4.407 -         if (res) return res;
   4.408 -      }
   4.409 -      lib = lib->next;
   4.410 -   }
   4.411 -   return NULL;
   4.412 +  const char* res = NULL;
   4.413 +  lib_info* lib = ph->libs;
   4.414 +  while (lib) {
   4.415 +    if (lib->symtab && addr >= lib->base) {
   4.416 +      res = nearest_symbol(lib->symtab, addr - lib->base, poffset);
   4.417 +      if (res) return res;
   4.418 +    }
   4.419 +    lib = lib->next;
   4.420 +  }
   4.421 +  return NULL;
   4.422  }
   4.423  
   4.424  // add a thread to ps_prochandle
   4.425 -thread_info* add_thread_info(struct ps_prochandle* ph, pthread_t pthread_id, lwpid_t lwp_id) {
   4.426 -   thread_info* newthr;
   4.427 -   if ( (newthr = (thread_info*) calloc(1, sizeof(thread_info))) == NULL) {
   4.428 -      print_debug("can't allocate memory for thread_info\n");
   4.429 -      return NULL;
   4.430 -   }
   4.431 +sa_thread_info* add_thread_info(struct ps_prochandle* ph, pthread_t pthread_id, lwpid_t lwp_id) {
   4.432 +  sa_thread_info* newthr;
   4.433 +  if ( (newthr = (sa_thread_info*) calloc(1, sizeof(sa_thread_info))) == NULL) {
   4.434 +    print_debug("can't allocate memory for thread_info\n");
   4.435 +    return NULL;
   4.436 +  }
   4.437  
   4.438 -   // initialize thread info
   4.439 -   newthr->pthread_id = pthread_id;
   4.440 -   newthr->lwp_id = lwp_id;
   4.441 +  // initialize thread info
   4.442 +  newthr->pthread_id = pthread_id;
   4.443 +  newthr->lwp_id = lwp_id;
   4.444  
   4.445 -   // add new thread to the list
   4.446 -   newthr->next = ph->threads;
   4.447 -   ph->threads = newthr;
   4.448 -   ph->num_threads++;
   4.449 -   return newthr;
   4.450 +  // add new thread to the list
   4.451 +  newthr->next = ph->threads;
   4.452 +  ph->threads = newthr;
   4.453 +  ph->num_threads++;
   4.454 +  return newthr;
   4.455  }
   4.456  
   4.457 -
   4.458 +#ifndef __APPLE__
   4.459  // struct used for client data from thread_db callback
   4.460  struct thread_db_client_data {
   4.461 -   struct ps_prochandle* ph;
   4.462 -   thread_info_callback callback;
   4.463 +  struct ps_prochandle* ph;
   4.464 +  thread_info_callback callback;
   4.465  };
   4.466  
   4.467  // callback function for libthread_db
   4.468 @@ -314,6 +375,7 @@
   4.469    return true;
   4.470  }
   4.471  
   4.472 +#endif // __APPLE__
   4.473  
   4.474  // get number of threads
   4.475  int get_num_threads(struct ps_prochandle* ph) {
   4.476 @@ -322,18 +384,54 @@
   4.477  
   4.478  // get lwp_id of n'th thread
   4.479  lwpid_t get_lwp_id(struct ps_prochandle* ph, int index) {
   4.480 -   int count = 0;
   4.481 -   thread_info* thr = ph->threads;
   4.482 -   while (thr) {
   4.483 -      if (count == index) {
   4.484 -         return thr->lwp_id;
   4.485 -      }
   4.486 -      count++;
   4.487 -      thr = thr->next;
   4.488 -   }
   4.489 -   return -1;
   4.490 +  int count = 0;
   4.491 +  sa_thread_info* thr = ph->threads;
   4.492 +  while (thr) {
   4.493 +    if (count == index) {
   4.494 +      return thr->lwp_id;
   4.495 +    }
   4.496 +    count++;
   4.497 +    thr = thr->next;
   4.498 +  }
   4.499 +  return 0;
   4.500  }
   4.501  
   4.502 +#ifdef __APPLE__
   4.503 +// set lwp_id of n'th thread
   4.504 +bool set_lwp_id(struct ps_prochandle* ph, int index, lwpid_t lwpid) {
   4.505 +  int count = 0;
   4.506 +  sa_thread_info* thr = ph->threads;
   4.507 +  while (thr) {
   4.508 +    if (count == index) {
   4.509 +      thr->lwp_id = lwpid;
   4.510 +      return true;
   4.511 +    }
   4.512 +    count++;
   4.513 +    thr = thr->next;
   4.514 +  }
   4.515 +  return false;
   4.516 +}
   4.517 +
   4.518 +// get regs of n-th thread, only used in fillThreads the first time called
   4.519 +bool get_nth_lwp_regs(struct ps_prochandle* ph, int index, struct reg* regs) {
   4.520 +  int count = 0;
   4.521 +  sa_thread_info* thr = ph->threads;
   4.522 +  while (thr) {
   4.523 +    if (count == index) {
   4.524 +      break;
   4.525 +    }
   4.526 +    count++;
   4.527 +    thr = thr->next;
   4.528 +  }
   4.529 +  if (thr != NULL) {
   4.530 +    memcpy(regs, &thr->regs, sizeof(struct reg));
   4.531 +    return true;
   4.532 +  }
   4.533 +  return false;
   4.534 +}
   4.535 +
   4.536 +#endif // __APPLE__
   4.537 +
   4.538  // get regs for a given lwp
   4.539  bool get_lwp_regs(struct ps_prochandle* ph, lwpid_t lwp_id, struct reg* regs) {
   4.540    return ph->ops->get_lwp_regs(ph, lwp_id, regs);
   4.541 @@ -341,35 +439,35 @@
   4.542  
   4.543  // get number of shared objects
   4.544  int get_num_libs(struct ps_prochandle* ph) {
   4.545 -   return ph->num_libs;
   4.546 +  return ph->num_libs;
   4.547  }
   4.548  
   4.549  // get name of n'th solib
   4.550  const char* get_lib_name(struct ps_prochandle* ph, int index) {
   4.551 -   int count = 0;
   4.552 -   lib_info* lib = ph->libs;
   4.553 -   while (lib) {
   4.554 -      if (count == index) {
   4.555 -         return lib->name;
   4.556 -      }
   4.557 -      count++;
   4.558 -      lib = lib->next;
   4.559 -   }
   4.560 -   return NULL;
   4.561 +  int count = 0;
   4.562 +  lib_info* lib = ph->libs;
   4.563 +  while (lib) {
   4.564 +    if (count == index) {
   4.565 +      return lib->name;
   4.566 +    }
   4.567 +    count++;
   4.568 +    lib = lib->next;
   4.569 +  }
   4.570 +  return NULL;
   4.571  }
   4.572  
   4.573  // get base address of a lib
   4.574  uintptr_t get_lib_base(struct ps_prochandle* ph, int index) {
   4.575 -   int count = 0;
   4.576 -   lib_info* lib = ph->libs;
   4.577 -   while (lib) {
   4.578 -      if (count == index) {
   4.579 -         return lib->base;
   4.580 -      }
   4.581 -      count++;
   4.582 -      lib = lib->next;
   4.583 -   }
   4.584 -   return (uintptr_t)NULL;
   4.585 +  int count = 0;
   4.586 +  lib_info* lib = ph->libs;
   4.587 +  while (lib) {
   4.588 +    if (count == index) {
   4.589 +      return lib->base;
   4.590 +    }
   4.591 +    count++;
   4.592 +    lib = lib->next;
   4.593 +  }
   4.594 +  return (uintptr_t)NULL;
   4.595  }
   4.596  
   4.597  bool find_lib(struct ps_prochandle* ph, const char *lib_name) {
   4.598 @@ -425,6 +523,7 @@
   4.599    va_end(alist);
   4.600  }
   4.601  
   4.602 +#ifndef __APPLE__
   4.603  // ------------------------------------------------------------------------
   4.604  // Functions below this point are not yet implemented. They are here only
   4.605  // to make the linker happy.
   4.606 @@ -458,3 +557,4 @@
   4.607    print_debug("ps_pcontinue not implemented\n");
   4.608    return PS_OK;
   4.609  }
   4.610 +#endif // __APPLE__
     5.1 --- a/agent/src/os/bsd/libproc_impl.h	Fri Mar 15 11:44:33 2013 -0700
     5.2 +++ b/agent/src/os/bsd/libproc_impl.h	Sun Mar 17 08:57:56 2013 -0700
     5.3 @@ -30,6 +30,60 @@
     5.4  #include "libproc.h"
     5.5  #include "symtab.h"
     5.6  
     5.7 +#ifdef __APPLE__
     5.8 +#include <inttypes.h>     // for PRIx64, 32, ...
     5.9 +#include <pthread.h>
    5.10 +#include <mach-o/loader.h>
    5.11 +#include <mach-o/nlist.h>
    5.12 +#include <mach-o/fat.h>
    5.13 +
    5.14 +#ifndef register_t
    5.15 +#define register_t uint64_t
    5.16 +#endif
    5.17 +
    5.18 +/*** registers copied from bsd/amd64 */
    5.19 +typedef struct reg {
    5.20 +  register_t      r_r15;
    5.21 +  register_t      r_r14;
    5.22 +  register_t      r_r13;
    5.23 +  register_t      r_r12;
    5.24 +  register_t      r_r11;
    5.25 +  register_t      r_r10;
    5.26 +  register_t      r_r9;
    5.27 +  register_t      r_r8;
    5.28 +  register_t      r_rdi;
    5.29 +  register_t      r_rsi;
    5.30 +  register_t      r_rbp;
    5.31 +  register_t      r_rbx;
    5.32 +  register_t      r_rdx;
    5.33 +  register_t      r_rcx;
    5.34 +  register_t      r_rax;
    5.35 +  uint32_t        r_trapno;      // not used
    5.36 +  uint16_t        r_fs;
    5.37 +  uint16_t        r_gs;
    5.38 +  uint32_t        r_err;         // not used
    5.39 +  uint16_t        r_es;          // not used
    5.40 +  uint16_t        r_ds;          // not used
    5.41 +  register_t      r_rip;
    5.42 +  register_t      r_cs;
    5.43 +  register_t      r_rflags;
    5.44 +  register_t      r_rsp;
    5.45 +  register_t      r_ss;          // not used
    5.46 +} reg;
    5.47 +
    5.48 +// convenient defs
    5.49 +typedef struct mach_header_64 mach_header_64;
    5.50 +typedef struct load_command load_command;
    5.51 +typedef struct segment_command_64 segment_command_64;
    5.52 +typedef struct thread_command thread_command;
    5.53 +typedef struct dylib_command dylib_command;
    5.54 +typedef struct symtab_command symtab_command;
    5.55 +typedef struct nlist_64 nlist_64;
    5.56 +#else
    5.57 +#include <thread_db.h>
    5.58 +#include "salibelf.h"
    5.59 +#endif //  __APPLE__
    5.60 +
    5.61  // data structures in this file mimic those of Solaris 8.0 - libproc's Pcontrol.h
    5.62  
    5.63  #define BUF_SIZE     (PATH_MAX + NAME_MAX + 1)
    5.64 @@ -44,12 +98,12 @@
    5.65  } lib_info;
    5.66  
    5.67  // list of threads
    5.68 -typedef struct thread_info {
    5.69 -   lwpid_t                  lwp_id;
    5.70 -   pthread_t                pthread_id; // not used cores, always -1
    5.71 +typedef struct sa_thread_info {
    5.72 +   lwpid_t                  lwp_id;     // same as pthread_t
    5.73 +   pthread_t                pthread_id; //
    5.74     struct reg               regs;       // not for process, core uses for caching regset
    5.75 -   struct thread_info*      next;
    5.76 -} thread_info;
    5.77 +   struct sa_thread_info*   next;
    5.78 +} sa_thread_info;
    5.79  
    5.80  // list of virtual memory maps
    5.81  typedef struct map_info {
    5.82 @@ -91,6 +145,7 @@
    5.83     // part of the class sharing workaround
    5.84     map_info*          class_share_maps;// class share maps in a linked list
    5.85     map_info**         map_array; // sorted (by vaddr) array of map_info pointers
    5.86 +   char               exec_path[4096];  // file name java
    5.87  };
    5.88  
    5.89  struct ps_prochandle {
    5.90 @@ -100,12 +155,11 @@
    5.91     lib_info*          libs;      // head of lib list
    5.92     lib_info*          lib_tail;  // tail of lib list - to append at the end
    5.93     int                num_threads;
    5.94 -   thread_info*       threads;   // head of thread list
    5.95 +   sa_thread_info*    threads;   // head of thread list
    5.96     struct core_data*  core;      // data only used for core dumps, NULL for process
    5.97  };
    5.98  
    5.99  int pathmap_open(const char* name);
   5.100 -
   5.101  void print_debug(const char* format,...);
   5.102  void print_error(const char* format,...);
   5.103  bool is_debug();
   5.104 @@ -122,10 +176,45 @@
   5.105  lib_info* add_lib_info_fd(struct ps_prochandle* ph, const char* libname, int fd,
   5.106                            uintptr_t base);
   5.107  
   5.108 -// adds a new thread to threads list, returns NULL on failure
   5.109 -thread_info* add_thread_info(struct ps_prochandle* ph, pthread_t pthread_id, lwpid_t lwp_id);
   5.110 +sa_thread_info* add_thread_info(struct ps_prochandle* ph, pthread_t pthread_id, lwpid_t lwp_id);
   5.111 +// a test for ELF signature without using libelf
   5.112  
   5.113 -// a test for ELF signature without using libelf
   5.114 +#ifdef __APPLE__
   5.115 +// a test for Mach-O signature
   5.116 +bool is_macho_file(int fd);
   5.117 +// skip fat head to get image start offset of cpu_type_t
   5.118 +// return false if any error happens, else value in offset.
   5.119 +bool get_arch_off(int fd, cpu_type_t cputype, off_t *offset);
   5.120 +#else
   5.121  bool is_elf_file(int fd);
   5.122 +#endif // __APPLE__
   5.123  
   5.124 +lwpid_t get_lwp_id(struct ps_prochandle* ph, int index);
   5.125 +bool set_lwp_id(struct ps_prochandle* ph, int index, lwpid_t lwpid);
   5.126 +bool get_nth_lwp_regs(struct ps_prochandle* ph, int index, struct reg* regs);
   5.127 +
   5.128 +// ps_pglobal_lookup() looks up the symbol sym_name in the symbol table
   5.129 +// of the load object object_name in the target process identified by ph.
   5.130 +// It returns the symbol's value as an address in the target process in
   5.131 +// *sym_addr.
   5.132 +
   5.133 +ps_err_e ps_pglobal_lookup(struct ps_prochandle *ph, const char *object_name,
   5.134 +                    const char *sym_name, psaddr_t *sym_addr);
   5.135 +
   5.136 +// read "size" bytes info "buf" from address "addr"
   5.137 +ps_err_e ps_pread(struct ps_prochandle *ph, psaddr_t  addr,
   5.138 +                  void *buf, size_t size);
   5.139 +
   5.140 +// write "size" bytes of data to debuggee at address "addr"
   5.141 +ps_err_e ps_pwrite(struct ps_prochandle *ph, psaddr_t addr,
   5.142 +                   const void *buf, size_t size);
   5.143 +
   5.144 +// fill in ptrace_lwpinfo for lid
   5.145 +ps_err_e ps_linfo(struct ps_prochandle *ph, lwpid_t lwp_id, void *linfo);
   5.146 +
   5.147 +// needed for when libthread_db is compiled with TD_DEBUG defined
   5.148 +void ps_plog (const char *format, ...);
   5.149 +
   5.150 +// untility, tells the position in file
   5.151 +off_t ltell(int fd);
   5.152  #endif //_LIBPROC_IMPL_H_
     6.1 --- a/agent/src/os/bsd/ps_core.c	Fri Mar 15 11:44:33 2013 -0700
     6.2 +++ b/agent/src/os/bsd/ps_core.c	Sun Mar 17 08:57:56 2013 -0700
     6.3 @@ -1,5 +1,5 @@
     6.4  /*
     6.5 - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
     6.6 + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
     6.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     6.8   *
     6.9   * This code is free software; you can redistribute it and/or modify it
    6.10 @@ -28,10 +28,11 @@
    6.11  #include <string.h>
    6.12  #include <stdlib.h>
    6.13  #include <stddef.h>
    6.14 -#include <elf.h>
    6.15 -#include <link.h>
    6.16  #include "libproc_impl.h"
    6.17 -#include "salibelf.h"
    6.18 +
    6.19 +#ifdef __APPLE__
    6.20 +#include "sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext.h"
    6.21 +#endif
    6.22  
    6.23  // This file has the libproc implementation to read core files.
    6.24  // For live processes, refer to ps_proc.c. Portions of this is adapted
    6.25 @@ -41,156 +42,158 @@
    6.26  // ps_prochandle cleanup helper functions
    6.27  
    6.28  // close all file descriptors
    6.29 -static void close_elf_files(struct ps_prochandle* ph) {
    6.30 -   lib_info* lib = NULL;
    6.31 +static void close_files(struct ps_prochandle* ph) {
    6.32 +  lib_info* lib = NULL;
    6.33 +  // close core file descriptor
    6.34 +  if (ph->core->core_fd >= 0)
    6.35 +    close(ph->core->core_fd);
    6.36  
    6.37 -   // close core file descriptor
    6.38 -   if (ph->core->core_fd >= 0)
    6.39 -     close(ph->core->core_fd);
    6.40 +  // close exec file descriptor
    6.41 +  if (ph->core->exec_fd >= 0)
    6.42 +    close(ph->core->exec_fd);
    6.43  
    6.44 -   // close exec file descriptor
    6.45 -   if (ph->core->exec_fd >= 0)
    6.46 -     close(ph->core->exec_fd);
    6.47 +  // close interp file descriptor
    6.48 +  if (ph->core->interp_fd >= 0)
    6.49 +    close(ph->core->interp_fd);
    6.50  
    6.51 -   // close interp file descriptor
    6.52 -   if (ph->core->interp_fd >= 0)
    6.53 -     close(ph->core->interp_fd);
    6.54 +  // close class share archive file
    6.55 +  if (ph->core->classes_jsa_fd >= 0)
    6.56 +    close(ph->core->classes_jsa_fd);
    6.57  
    6.58 -   // close class share archive file
    6.59 -   if (ph->core->classes_jsa_fd >= 0)
    6.60 -     close(ph->core->classes_jsa_fd);
    6.61 -
    6.62 -   // close all library file descriptors
    6.63 -   lib = ph->libs;
    6.64 -   while (lib) {
    6.65 -      int fd = lib->fd;
    6.66 -      if (fd >= 0 && fd != ph->core->exec_fd) close(fd);
    6.67 -      lib = lib->next;
    6.68 -   }
    6.69 +  // close all library file descriptors
    6.70 +  lib = ph->libs;
    6.71 +  while (lib) {
    6.72 +    int fd = lib->fd;
    6.73 +    if (fd >= 0 && fd != ph->core->exec_fd) {
    6.74 +      close(fd);
    6.75 +    }
    6.76 +    lib = lib->next;
    6.77 +  }
    6.78  }
    6.79  
    6.80  // clean all map_info stuff
    6.81  static void destroy_map_info(struct ps_prochandle* ph) {
    6.82    map_info* map = ph->core->maps;
    6.83    while (map) {
    6.84 -     map_info* next = map->next;
    6.85 -     free(map);
    6.86 -     map = next;
    6.87 +    map_info* next = map->next;
    6.88 +    free(map);
    6.89 +    map = next;
    6.90    }
    6.91  
    6.92    if (ph->core->map_array) {
    6.93 -     free(ph->core->map_array);
    6.94 +    free(ph->core->map_array);
    6.95    }
    6.96  
    6.97    // Part of the class sharing workaround
    6.98    map = ph->core->class_share_maps;
    6.99    while (map) {
   6.100 -     map_info* next = map->next;
   6.101 -     free(map);
   6.102 -     map = next;
   6.103 +    map_info* next = map->next;
   6.104 +    free(map);
   6.105 +    map = next;
   6.106    }
   6.107  }
   6.108  
   6.109  // ps_prochandle operations
   6.110  static void core_release(struct ps_prochandle* ph) {
   6.111 -   if (ph->core) {
   6.112 -      close_elf_files(ph);
   6.113 -      destroy_map_info(ph);
   6.114 -      free(ph->core);
   6.115 -   }
   6.116 +  if (ph->core) {
   6.117 +    close_files(ph);
   6.118 +    destroy_map_info(ph);
   6.119 +    free(ph->core);
   6.120 +  }
   6.121  }
   6.122  
   6.123  static map_info* allocate_init_map(int fd, off_t offset, uintptr_t vaddr, size_t memsz) {
   6.124 -   map_info* map;
   6.125 -   if ( (map = (map_info*) calloc(1, sizeof(map_info))) == NULL) {
   6.126 -      print_debug("can't allocate memory for map_info\n");
   6.127 -      return NULL;
   6.128 -   }
   6.129 +  map_info* map;
   6.130 +  if ( (map = (map_info*) calloc(1, sizeof(map_info))) == NULL) {
   6.131 +    print_debug("can't allocate memory for map_info\n");
   6.132 +    return NULL;
   6.133 +  }
   6.134  
   6.135 -   // initialize map
   6.136 -   map->fd     = fd;
   6.137 -   map->offset = offset;
   6.138 -   map->vaddr  = vaddr;
   6.139 -   map->memsz  = memsz;
   6.140 -   return map;
   6.141 +  // initialize map
   6.142 +  map->fd     = fd;
   6.143 +  map->offset = offset;
   6.144 +  map->vaddr  = vaddr;
   6.145 +  map->memsz  = memsz;
   6.146 +  return map;
   6.147  }
   6.148  
   6.149  // add map info with given fd, offset, vaddr and memsz
   6.150  static map_info* add_map_info(struct ps_prochandle* ph, int fd, off_t offset,
   6.151                               uintptr_t vaddr, size_t memsz) {
   6.152 -   map_info* map;
   6.153 -   if ((map = allocate_init_map(fd, offset, vaddr, memsz)) == NULL) {
   6.154 -      return NULL;
   6.155 -   }
   6.156 +  map_info* map;
   6.157 +  if ((map = allocate_init_map(fd, offset, vaddr, memsz)) == NULL) {
   6.158 +    return NULL;
   6.159 +  }
   6.160  
   6.161 -   // add this to map list
   6.162 -   map->next  = ph->core->maps;
   6.163 -   ph->core->maps   = map;
   6.164 -   ph->core->num_maps++;
   6.165 +  // add this to map list
   6.166 +  map->next  = ph->core->maps;
   6.167 +  ph->core->maps   = map;
   6.168 +  ph->core->num_maps++;
   6.169  
   6.170 -   return map;
   6.171 +  return map;
   6.172  }
   6.173  
   6.174  // Part of the class sharing workaround
   6.175  static map_info* add_class_share_map_info(struct ps_prochandle* ph, off_t offset,
   6.176                               uintptr_t vaddr, size_t memsz) {
   6.177 -   map_info* map;
   6.178 -   if ((map = allocate_init_map(ph->core->classes_jsa_fd,
   6.179 -                                offset, vaddr, memsz)) == NULL) {
   6.180 -      return NULL;
   6.181 -   }
   6.182 +  map_info* map;
   6.183 +  if ((map = allocate_init_map(ph->core->classes_jsa_fd,
   6.184 +                               offset, vaddr, memsz)) == NULL) {
   6.185 +    return NULL;
   6.186 +  }
   6.187  
   6.188 -   map->next = ph->core->class_share_maps;
   6.189 -   ph->core->class_share_maps = map;
   6.190 -   return map;
   6.191 +  map->next = ph->core->class_share_maps;
   6.192 +  ph->core->class_share_maps = map;
   6.193 +  return map;
   6.194  }
   6.195  
   6.196  // Return the map_info for the given virtual address.  We keep a sorted
   6.197  // array of pointers in ph->map_array, so we can binary search.
   6.198  static map_info* core_lookup(struct ps_prochandle *ph, uintptr_t addr)
   6.199  {
   6.200 -   int mid, lo = 0, hi = ph->core->num_maps - 1;
   6.201 -   map_info *mp;
   6.202 +  int mid, lo = 0, hi = ph->core->num_maps - 1;
   6.203 +  map_info *mp;
   6.204  
   6.205 -   while (hi - lo > 1) {
   6.206 -     mid = (lo + hi) / 2;
   6.207 -      if (addr >= ph->core->map_array[mid]->vaddr)
   6.208 -         lo = mid;
   6.209 -      else
   6.210 -         hi = mid;
   6.211 -   }
   6.212 +  while (hi - lo > 1) {
   6.213 +    mid = (lo + hi) / 2;
   6.214 +    if (addr >= ph->core->map_array[mid]->vaddr) {
   6.215 +      lo = mid;
   6.216 +    } else {
   6.217 +      hi = mid;
   6.218 +    }
   6.219 +  }
   6.220  
   6.221 -   if (addr < ph->core->map_array[hi]->vaddr)
   6.222 -      mp = ph->core->map_array[lo];
   6.223 -   else
   6.224 -      mp = ph->core->map_array[hi];
   6.225 +  if (addr < ph->core->map_array[hi]->vaddr) {
   6.226 +    mp = ph->core->map_array[lo];
   6.227 +  } else {
   6.228 +    mp = ph->core->map_array[hi];
   6.229 +  }
   6.230  
   6.231 -   if (addr >= mp->vaddr && addr < mp->vaddr + mp->memsz)
   6.232 +  if (addr >= mp->vaddr && addr < mp->vaddr + mp->memsz) {
   6.233 +    return (mp);
   6.234 +  }
   6.235 +
   6.236 +
   6.237 +  // Part of the class sharing workaround
   6.238 +  // Unfortunately, we have no way of detecting -Xshare state.
   6.239 +  // Check out the share maps atlast, if we don't find anywhere.
   6.240 +  // This is done this way so to avoid reading share pages
   6.241 +  // ahead of other normal maps. For eg. with -Xshare:off we don't
   6.242 +  // want to prefer class sharing data to data from core.
   6.243 +  mp = ph->core->class_share_maps;
   6.244 +  if (mp) {
   6.245 +    print_debug("can't locate map_info at 0x%lx, trying class share maps\n", addr);
   6.246 +  }
   6.247 +  while (mp) {
   6.248 +    if (addr >= mp->vaddr && addr < mp->vaddr + mp->memsz) {
   6.249 +      print_debug("located map_info at 0x%lx from class share maps\n", addr);
   6.250        return (mp);
   6.251 +    }
   6.252 +    mp = mp->next;
   6.253 +  }
   6.254  
   6.255 -
   6.256 -   // Part of the class sharing workaround
   6.257 -   // Unfortunately, we have no way of detecting -Xshare state.
   6.258 -   // Check out the share maps atlast, if we don't find anywhere.
   6.259 -   // This is done this way so to avoid reading share pages
   6.260 -   // ahead of other normal maps. For eg. with -Xshare:off we don't
   6.261 -   // want to prefer class sharing data to data from core.
   6.262 -   mp = ph->core->class_share_maps;
   6.263 -   if (mp) {
   6.264 -      print_debug("can't locate map_info at 0x%lx, trying class share maps\n",
   6.265 -             addr);
   6.266 -   }
   6.267 -   while (mp) {
   6.268 -      if (addr >= mp->vaddr && addr < mp->vaddr + mp->memsz) {
   6.269 -         print_debug("located map_info at 0x%lx from class share maps\n",
   6.270 -                  addr);
   6.271 -         return (mp);
   6.272 -      }
   6.273 -      mp = mp->next;
   6.274 -   }
   6.275 -
   6.276 -   print_debug("can't locate map_info at 0x%lx\n", addr);
   6.277 -   return (NULL);
   6.278 +  print_debug("can't locate map_info at 0x%lx\n", addr);
   6.279 +  return (NULL);
   6.280  }
   6.281  
   6.282  //---------------------------------------------------------------
   6.283 @@ -239,157 +242,171 @@
   6.284  };
   6.285  
   6.286  static bool read_jboolean(struct ps_prochandle* ph, uintptr_t addr, jboolean* pvalue) {
   6.287 -   jboolean i;
   6.288 -   if (ps_pread(ph, (psaddr_t) addr, &i, sizeof(i)) == PS_OK) {
   6.289 -      *pvalue = i;
   6.290 -      return true;
   6.291 -   } else {
   6.292 -      return false;
   6.293 -   }
   6.294 +  jboolean i;
   6.295 +  if (ps_pread(ph, (psaddr_t) addr, &i, sizeof(i)) == PS_OK) {
   6.296 +    *pvalue = i;
   6.297 +    return true;
   6.298 +  } else {
   6.299 +    return false;
   6.300 +  }
   6.301  }
   6.302  
   6.303  static bool read_pointer(struct ps_prochandle* ph, uintptr_t addr, uintptr_t* pvalue) {
   6.304 -   uintptr_t uip;
   6.305 -   if (ps_pread(ph, (psaddr_t) addr, &uip, sizeof(uip)) == PS_OK) {
   6.306 -      *pvalue = uip;
   6.307 -      return true;
   6.308 -   } else {
   6.309 -      return false;
   6.310 -   }
   6.311 +  uintptr_t uip;
   6.312 +  if (ps_pread(ph, (psaddr_t) addr, (char *)&uip, sizeof(uip)) == PS_OK) {
   6.313 +    *pvalue = uip;
   6.314 +    return true;
   6.315 +  } else {
   6.316 +    return false;
   6.317 +  }
   6.318  }
   6.319  
   6.320  // used to read strings from debuggee
   6.321  static bool read_string(struct ps_prochandle* ph, uintptr_t addr, char* buf, size_t size) {
   6.322 -   size_t i = 0;
   6.323 -   char  c = ' ';
   6.324 +  size_t i = 0;
   6.325 +  char  c = ' ';
   6.326  
   6.327 -   while (c != '\0') {
   6.328 -     if (ps_pread(ph, (psaddr_t) addr, &c, sizeof(char)) != PS_OK)
   6.329 -         return false;
   6.330 -      if (i < size - 1)
   6.331 -         buf[i] = c;
   6.332 -      else // smaller buffer
   6.333 -         return false;
   6.334 -      i++; addr++;
   6.335 -   }
   6.336 -
   6.337 -   buf[i] = '\0';
   6.338 -   return true;
   6.339 +  while (c != '\0') {
   6.340 +    if (ps_pread(ph, (psaddr_t) addr, &c, sizeof(char)) != PS_OK) {
   6.341 +      return false;
   6.342 +    }
   6.343 +    if (i < size - 1) {
   6.344 +      buf[i] = c;
   6.345 +    } else {
   6.346 +      // smaller buffer
   6.347 +      return false;
   6.348 +    }
   6.349 +    i++; addr++;
   6.350 +  }
   6.351 +  buf[i] = '\0';
   6.352 +  return true;
   6.353  }
   6.354  
   6.355 +#ifdef __APPLE__
   6.356 +#define USE_SHARED_SPACES_SYM "_UseSharedSpaces"
   6.357 +// mangled name of Arguments::SharedArchivePath
   6.358 +#define SHARED_ARCHIVE_PATH_SYM "_ZN9Arguments17SharedArchivePathE"
   6.359 +#else
   6.360  #define USE_SHARED_SPACES_SYM "UseSharedSpaces"
   6.361  // mangled name of Arguments::SharedArchivePath
   6.362 -#define SHARED_ARCHIVE_PATH_SYM "_ZN9Arguments17SharedArchivePathE"
   6.363 +#define SHARED_ARCHIVE_PATH_SYM "__ZN9Arguments17SharedArchivePathE"
   6.364 +#endif // __APPLE_
   6.365  
   6.366  static bool init_classsharing_workaround(struct ps_prochandle* ph) {
   6.367 -   lib_info* lib = ph->libs;
   6.368 -   while (lib != NULL) {
   6.369 -      // we are iterating over shared objects from the core dump. look for
   6.370 -      // libjvm[_g].so.
   6.371 -      const char *jvm_name = 0;
   6.372 -      if ((jvm_name = strstr(lib->name, "/libjvm.so")) != 0 ||
   6.373 -          (jvm_name = strstr(lib->name, "/libjvm_g.so")) != 0) {
   6.374 -         char classes_jsa[PATH_MAX];
   6.375 -         struct FileMapHeader header;
   6.376 -         size_t n = 0;
   6.377 -         int fd = -1, m = 0;
   6.378 -         uintptr_t base = 0, useSharedSpacesAddr = 0;
   6.379 -         uintptr_t sharedArchivePathAddrAddr = 0, sharedArchivePathAddr = 0;
   6.380 -         jboolean useSharedSpaces = 0;
   6.381 +  int m;
   6.382 +  size_t n;
   6.383 +  lib_info* lib = ph->libs;
   6.384 +  while (lib != NULL) {
   6.385 +    // we are iterating over shared objects from the core dump. look for
   6.386 +    // libjvm[_g].so.
   6.387 +    const char *jvm_name = 0;
   6.388 +#ifdef __APPLE__
   6.389 +    if ((jvm_name = strstr(lib->name, "/libjvm.dylib")) != 0 ||
   6.390 +        (jvm_name = strstr(lib->name, "/libjvm_g.dylib")) != 0)
   6.391 +#else
   6.392 +    if ((jvm_name = strstr(lib->name, "/libjvm.so")) != 0 ||
   6.393 +        (jvm_name = strstr(lib->name, "/libjvm_g.so")) != 0)
   6.394 +#endif // __APPLE__
   6.395 +    {
   6.396 +      char classes_jsa[PATH_MAX];
   6.397 +      struct FileMapHeader header;
   6.398 +      int fd = -1;
   6.399 +      uintptr_t base = 0, useSharedSpacesAddr = 0;
   6.400 +      uintptr_t sharedArchivePathAddrAddr = 0, sharedArchivePathAddr = 0;
   6.401 +      jboolean useSharedSpaces = 0;
   6.402  
   6.403 -         memset(classes_jsa, 0, sizeof(classes_jsa));
   6.404 -         jvm_name = lib->name;
   6.405 -         useSharedSpacesAddr = lookup_symbol(ph, jvm_name, USE_SHARED_SPACES_SYM);
   6.406 -         if (useSharedSpacesAddr == 0) {
   6.407 -            print_debug("can't lookup 'UseSharedSpaces' flag\n");
   6.408 -            return false;
   6.409 -         }
   6.410 +      memset(classes_jsa, 0, sizeof(classes_jsa));
   6.411 +      jvm_name = lib->name;
   6.412 +      useSharedSpacesAddr = lookup_symbol(ph, jvm_name, USE_SHARED_SPACES_SYM);
   6.413 +      if (useSharedSpacesAddr == 0) {
   6.414 +        print_debug("can't lookup 'UseSharedSpaces' flag\n");
   6.415 +        return false;
   6.416 +      }
   6.417  
   6.418 -         // Hotspot vm types are not exported to build this library. So
   6.419 -         // using equivalent type jboolean to read the value of
   6.420 -         // UseSharedSpaces which is same as hotspot type "bool".
   6.421 -         if (read_jboolean(ph, useSharedSpacesAddr, &useSharedSpaces) != true) {
   6.422 -            print_debug("can't read the value of 'UseSharedSpaces' flag\n");
   6.423 -            return false;
   6.424 -         }
   6.425 +      // Hotspot vm types are not exported to build this library. So
   6.426 +      // using equivalent type jboolean to read the value of
   6.427 +      // UseSharedSpaces which is same as hotspot type "bool".
   6.428 +      if (read_jboolean(ph, useSharedSpacesAddr, &useSharedSpaces) != true) {
   6.429 +        print_debug("can't read the value of 'UseSharedSpaces' flag\n");
   6.430 +        return false;
   6.431 +      }
   6.432  
   6.433 -         if ((int)useSharedSpaces == 0) {
   6.434 -            print_debug("UseSharedSpaces is false, assuming -Xshare:off!\n");
   6.435 -            return true;
   6.436 -         }
   6.437 +      if ((int)useSharedSpaces == 0) {
   6.438 +        print_debug("UseSharedSpaces is false, assuming -Xshare:off!\n");
   6.439 +        return true;
   6.440 +      }
   6.441  
   6.442 -         sharedArchivePathAddrAddr = lookup_symbol(ph, jvm_name, SHARED_ARCHIVE_PATH_SYM);
   6.443 -         if (sharedArchivePathAddrAddr == 0) {
   6.444 -            print_debug("can't lookup shared archive path symbol\n");
   6.445 -            return false;
   6.446 -         }
   6.447 +      sharedArchivePathAddrAddr = lookup_symbol(ph, jvm_name, SHARED_ARCHIVE_PATH_SYM);
   6.448 +      if (sharedArchivePathAddrAddr == 0) {
   6.449 +        print_debug("can't lookup shared archive path symbol\n");
   6.450 +        return false;
   6.451 +      }
   6.452  
   6.453 -         if (read_pointer(ph, sharedArchivePathAddrAddr, &sharedArchivePathAddr) != true) {
   6.454 -            print_debug("can't read shared archive path pointer\n");
   6.455 -            return false;
   6.456 -         }
   6.457 +      if (read_pointer(ph, sharedArchivePathAddrAddr, &sharedArchivePathAddr) != true) {
   6.458 +        print_debug("can't read shared archive path pointer\n");
   6.459 +        return false;
   6.460 +      }
   6.461  
   6.462 -         if (read_string(ph, sharedArchivePathAddr, classes_jsa, sizeof(classes_jsa)) != true) {
   6.463 -            print_debug("can't read shared archive path value\n");
   6.464 -            return false;
   6.465 -         }
   6.466 +      if (read_string(ph, sharedArchivePathAddr, classes_jsa, sizeof(classes_jsa)) != true) {
   6.467 +        print_debug("can't read shared archive path value\n");
   6.468 +        return false;
   6.469 +      }
   6.470  
   6.471 -         print_debug("looking for %s\n", classes_jsa);
   6.472 -         // open the class sharing archive file
   6.473 -         fd = pathmap_open(classes_jsa);
   6.474 -         if (fd < 0) {
   6.475 -            print_debug("can't open %s!\n", classes_jsa);
   6.476 -            ph->core->classes_jsa_fd = -1;
   6.477 -            return false;
   6.478 -         } else {
   6.479 -            print_debug("opened %s\n", classes_jsa);
   6.480 -         }
   6.481 +      print_debug("looking for %s\n", classes_jsa);
   6.482 +      // open the class sharing archive file
   6.483 +      fd = pathmap_open(classes_jsa);
   6.484 +      if (fd < 0) {
   6.485 +        print_debug("can't open %s!\n", classes_jsa);
   6.486 +        ph->core->classes_jsa_fd = -1;
   6.487 +        return false;
   6.488 +      } else {
   6.489 +        print_debug("opened %s\n", classes_jsa);
   6.490 +      }
   6.491  
   6.492 -         // read FileMapHeader from the file
   6.493 -         memset(&header, 0, sizeof(struct FileMapHeader));
   6.494 -         if ((n = read(fd, &header, sizeof(struct FileMapHeader)))
   6.495 -              != sizeof(struct FileMapHeader)) {
   6.496 -            print_debug("can't read shared archive file map header from %s\n", classes_jsa);
   6.497 -            close(fd);
   6.498 -            return false;
   6.499 -         }
   6.500 +      // read FileMapHeader from the file
   6.501 +      memset(&header, 0, sizeof(struct FileMapHeader));
   6.502 +      if ((n = read(fd, &header, sizeof(struct FileMapHeader)))
   6.503 +           != sizeof(struct FileMapHeader)) {
   6.504 +        print_debug("can't read shared archive file map header from %s\n", classes_jsa);
   6.505 +        close(fd);
   6.506 +        return false;
   6.507 +      }
   6.508  
   6.509 -         // check file magic
   6.510 -         if (header._magic != 0xf00baba2) {
   6.511 -            print_debug("%s has bad shared archive file magic number 0x%x, expecing 0xf00baba2\n",
   6.512 -                        classes_jsa, header._magic);
   6.513 -            close(fd);
   6.514 -            return false;
   6.515 -         }
   6.516 +      // check file magic
   6.517 +      if (header._magic != 0xf00baba2) {
   6.518 +        print_debug("%s has bad shared archive file magic number 0x%x, expecing 0xf00baba2\n",
   6.519 +                     classes_jsa, header._magic);
   6.520 +        close(fd);
   6.521 +        return false;
   6.522 +      }
   6.523  
   6.524 -         // check version
   6.525 -         if (header._version != CURRENT_ARCHIVE_VERSION) {
   6.526 -            print_debug("%s has wrong shared archive file version %d, expecting %d\n",
   6.527 -                        classes_jsa, header._version, CURRENT_ARCHIVE_VERSION);
   6.528 -            close(fd);
   6.529 -            return false;
   6.530 -         }
   6.531 +      // check version
   6.532 +      if (header._version != CURRENT_ARCHIVE_VERSION) {
   6.533 +        print_debug("%s has wrong shared archive file version %d, expecting %d\n",
   6.534 +                     classes_jsa, header._version, CURRENT_ARCHIVE_VERSION);
   6.535 +        close(fd);
   6.536 +        return false;
   6.537 +      }
   6.538  
   6.539 -         ph->core->classes_jsa_fd = fd;
   6.540 -         // add read-only maps from classes[_g].jsa to the list of maps
   6.541 -         for (m = 0; m < NUM_SHARED_MAPS; m++) {
   6.542 -            if (header._space[m]._read_only) {
   6.543 -               base = (uintptr_t) header._space[m]._base;
   6.544 -               // no need to worry about the fractional pages at-the-end.
   6.545 -               // possible fractional pages are handled by core_read_data.
   6.546 -               add_class_share_map_info(ph, (off_t) header._space[m]._file_offset,
   6.547 -                         base, (size_t) header._space[m]._used);
   6.548 -               print_debug("added a share archive map at 0x%lx\n", base);
   6.549 -            }
   6.550 -         }
   6.551 -         return true;
   6.552 +      ph->core->classes_jsa_fd = fd;
   6.553 +      // add read-only maps from classes[_g].jsa to the list of maps
   6.554 +      for (m = 0; m < NUM_SHARED_MAPS; m++) {
   6.555 +        if (header._space[m]._read_only) {
   6.556 +          base = (uintptr_t) header._space[m]._base;
   6.557 +          // no need to worry about the fractional pages at-the-end.
   6.558 +          // possible fractional pages are handled by core_read_data.
   6.559 +          add_class_share_map_info(ph, (off_t) header._space[m]._file_offset,
   6.560 +                                   base, (size_t) header._space[m]._used);
   6.561 +          print_debug("added a share archive map at 0x%lx\n", base);
   6.562 +        }
   6.563        }
   6.564 -      lib = lib->next;
   6.565 -   }
   6.566 -   return true;
   6.567 +      return true;
   6.568 +    }
   6.569 +    lib = lib->next;
   6.570 +  }
   6.571 +  return true;
   6.572  }
   6.573  
   6.574 -
   6.575  //---------------------------------------------------------------------------
   6.576  // functions to handle map_info
   6.577  
   6.578 @@ -397,54 +414,57 @@
   6.579  // callback for sorting the array of map_info pointers.
   6.580  static int core_cmp_mapping(const void *lhsp, const void *rhsp)
   6.581  {
   6.582 -   const map_info *lhs = *((const map_info **)lhsp);
   6.583 -   const map_info *rhs = *((const map_info **)rhsp);
   6.584 +  const map_info *lhs = *((const map_info **)lhsp);
   6.585 +  const map_info *rhs = *((const map_info **)rhsp);
   6.586  
   6.587 -   if (lhs->vaddr == rhs->vaddr)
   6.588 -      return (0);
   6.589 +  if (lhs->vaddr == rhs->vaddr) {
   6.590 +    return (0);
   6.591 +  }
   6.592  
   6.593 -   return (lhs->vaddr < rhs->vaddr ? -1 : 1);
   6.594 +  return (lhs->vaddr < rhs->vaddr ? -1 : 1);
   6.595  }
   6.596  
   6.597  // we sort map_info by starting virtual address so that we can do
   6.598  // binary search to read from an address.
   6.599  static bool sort_map_array(struct ps_prochandle* ph) {
   6.600 -   size_t num_maps = ph->core->num_maps;
   6.601 -   map_info* map = ph->core->maps;
   6.602 -   int i = 0;
   6.603 +  size_t num_maps = ph->core->num_maps;
   6.604 +  map_info* map = ph->core->maps;
   6.605 +  int i = 0;
   6.606  
   6.607 -   // allocate map_array
   6.608 -   map_info** array;
   6.609 -   if ( (array = (map_info**) malloc(sizeof(map_info*) * num_maps)) == NULL) {
   6.610 -      print_debug("can't allocate memory for map array\n");
   6.611 -      return false;
   6.612 -   }
   6.613 +  // allocate map_array
   6.614 +  map_info** array;
   6.615 +  if ( (array = (map_info**) malloc(sizeof(map_info*) * num_maps)) == NULL) {
   6.616 +     print_debug("can't allocate memory for map array\n");
   6.617 +     return false;
   6.618 +  }
   6.619  
   6.620 -   // add maps to array
   6.621 -   while (map) {
   6.622 -      array[i] = map;
   6.623 -      i++;
   6.624 -      map = map->next;
   6.625 -   }
   6.626 +  // add maps to array
   6.627 +  while (map) {
   6.628 +    array[i] = map;
   6.629 +    i++;
   6.630 +    map = map->next;
   6.631 +  }
   6.632  
   6.633 -   // sort is called twice. If this is second time, clear map array
   6.634 -   if (ph->core->map_array) free(ph->core->map_array);
   6.635 -   ph->core->map_array = array;
   6.636 -   // sort the map_info array by base virtual address.
   6.637 -   qsort(ph->core->map_array, ph->core->num_maps, sizeof (map_info*),
   6.638 -            core_cmp_mapping);
   6.639 +  // sort is called twice. If this is second time, clear map array
   6.640 +  if (ph->core->map_array) {
   6.641 +    free(ph->core->map_array);
   6.642 +  }
   6.643 +  ph->core->map_array = array;
   6.644 +  // sort the map_info array by base virtual address.
   6.645 +  qsort(ph->core->map_array, ph->core->num_maps, sizeof (map_info*),
   6.646 +           core_cmp_mapping);
   6.647  
   6.648 -   // print map
   6.649 -   if (is_debug()) {
   6.650 -      int j = 0;
   6.651 -      print_debug("---- sorted virtual address map ----\n");
   6.652 -      for (j = 0; j < ph->core->num_maps; j++) {
   6.653 -        print_debug("base = 0x%lx\tsize = %d\n", ph->core->map_array[j]->vaddr,
   6.654 -                                         ph->core->map_array[j]->memsz);
   6.655 -      }
   6.656 -   }
   6.657 +  // print map
   6.658 +  if (is_debug()) {
   6.659 +    int j = 0;
   6.660 +    print_debug("---- sorted virtual address map ----\n");
   6.661 +    for (j = 0; j < ph->core->num_maps; j++) {
   6.662 +      print_debug("base = 0x%lx\tsize = %d\n", ph->core->map_array[j]->vaddr,
   6.663 +                                       ph->core->map_array[j]->memsz);
   6.664 +    }
   6.665 +  }
   6.666  
   6.667 -   return true;
   6.668 +  return true;
   6.669  }
   6.670  
   6.671  #ifndef MIN
   6.672 @@ -461,16 +481,18 @@
   6.673        off_t off;
   6.674        int fd;
   6.675  
   6.676 -      if (mp == NULL)
   6.677 +      if (mp == NULL) {
   6.678           break;  /* No mapping for this address */
   6.679 +      }
   6.680  
   6.681        fd = mp->fd;
   6.682        mapoff = addr - mp->vaddr;
   6.683        len = MIN(resid, mp->memsz - mapoff);
   6.684        off = mp->offset + mapoff;
   6.685  
   6.686 -      if ((len = pread(fd, buf, len, off)) <= 0)
   6.687 +      if ((len = pread(fd, buf, len, off)) <= 0) {
   6.688           break;
   6.689 +      }
   6.690  
   6.691        resid -= len;
   6.692        addr += len;
   6.693 @@ -507,8 +529,8 @@
   6.694  
   6.695  static bool core_get_lwp_regs(struct ps_prochandle* ph, lwpid_t lwp_id,
   6.696                            struct reg* regs) {
   6.697 -   // for core we have cached the lwp regs from NOTE section
   6.698 -   thread_info* thr = ph->threads;
   6.699 +   // for core we have cached the lwp regs after segment parsed
   6.700 +   sa_thread_info* thr = ph->threads;
   6.701     while (thr) {
   6.702       if (thr->lwp_id == lwp_id) {
   6.703         memcpy(regs, &thr->regs, sizeof(struct reg));
   6.704 @@ -519,7 +541,7 @@
   6.705     return false;
   6.706  }
   6.707  
   6.708 -static bool core_get_lwp_info(struct ps_prochandle *ph, lwpid_t lwp_id, void *linfo) {
   6.709 +static bool core_get_lwp_info(struct ps_prochandle *ph, lwpid_t id, void *info) {
   6.710     print_debug("core_get_lwp_info not implemented\n");
   6.711     return false;
   6.712  }
   6.713 @@ -532,12 +554,451 @@
   6.714     .get_lwp_info= core_get_lwp_info
   6.715  };
   6.716  
   6.717 -// read regs and create thread from NT_PRSTATUS entries from core file
   6.718 +// from this point, mainly two blocks divided by def __APPLE__
   6.719 +// one for Macosx, the other for regular Bsd
   6.720 +
   6.721 +#ifdef __APPLE__
   6.722 +
   6.723 +void print_thread(sa_thread_info *threadinfo) {
   6.724 +  print_debug("thread added: %d\n", threadinfo->lwp_id);
   6.725 +  print_debug("registers:\n");
   6.726 +  print_debug("  r_r15: 0x%" PRIx64 "\n", threadinfo->regs.r_r15);
   6.727 +  print_debug("  r_r14: 0x%" PRIx64 "\n", threadinfo->regs.r_r14);
   6.728 +  print_debug("  r_r13: 0x%" PRIx64 "\n", threadinfo->regs.r_r13);
   6.729 +  print_debug("  r_r12: 0x%" PRIx64 "\n", threadinfo->regs.r_r12);
   6.730 +  print_debug("  r_r11: 0x%" PRIx64 "\n", threadinfo->regs.r_r11);
   6.731 +  print_debug("  r_r10: 0x%" PRIx64 "\n", threadinfo->regs.r_r10);
   6.732 +  print_debug("  r_r9:  0x%" PRIx64 "\n", threadinfo->regs.r_r9);
   6.733 +  print_debug("  r_r8:  0x%" PRIx64 "\n", threadinfo->regs.r_r8);
   6.734 +  print_debug("  r_rdi: 0x%" PRIx64 "\n", threadinfo->regs.r_rdi);
   6.735 +  print_debug("  r_rsi: 0x%" PRIx64 "\n", threadinfo->regs.r_rsi);
   6.736 +  print_debug("  r_rbp: 0x%" PRIx64 "\n", threadinfo->regs.r_rbp);
   6.737 +  print_debug("  r_rbx: 0x%" PRIx64 "\n", threadinfo->regs.r_rbx);
   6.738 +  print_debug("  r_rdx: 0x%" PRIx64 "\n", threadinfo->regs.r_rdx);
   6.739 +  print_debug("  r_rcx: 0x%" PRIx64 "\n", threadinfo->regs.r_rcx);
   6.740 +  print_debug("  r_rax: 0x%" PRIx64 "\n", threadinfo->regs.r_rax);
   6.741 +  print_debug("  r_fs:  0x%" PRIx32 "\n", threadinfo->regs.r_fs);
   6.742 +  print_debug("  r_gs:  0x%" PRIx32 "\n", threadinfo->regs.r_gs);
   6.743 +  print_debug("  r_rip  0x%" PRIx64 "\n", threadinfo->regs.r_rip);
   6.744 +  print_debug("  r_cs:  0x%" PRIx64 "\n", threadinfo->regs.r_cs);
   6.745 +  print_debug("  r_rsp: 0x%" PRIx64 "\n", threadinfo->regs.r_rsp);
   6.746 +  print_debug("  r_rflags: 0x%" PRIx64 "\n", threadinfo->regs.r_rflags);
   6.747 +}
   6.748 +
   6.749 +// read all segments64 commands from core file
   6.750 +// read all thread commands from core file
   6.751 +static bool read_core_segments(struct ps_prochandle* ph) {
   6.752 +  int i = 0;
   6.753 +  int num_threads = 0;
   6.754 +  int fd = ph->core->core_fd;
   6.755 +  off_t offset = 0;
   6.756 +  mach_header_64      fhead;
   6.757 +  load_command        lcmd;
   6.758 +  segment_command_64  segcmd;
   6.759 +  // thread_command      thrcmd;
   6.760 +
   6.761 +  lseek(fd, offset, SEEK_SET);
   6.762 +  if(read(fd, (void *)&fhead, sizeof(mach_header_64)) != sizeof(mach_header_64)) {
   6.763 +     goto err;
   6.764 +  }
   6.765 +  print_debug("total commands: %d\n", fhead.ncmds);
   6.766 +  offset += sizeof(mach_header_64);
   6.767 +  for (i = 0; i < fhead.ncmds; i++) {
   6.768 +    lseek(fd, offset, SEEK_SET);
   6.769 +    if (read(fd, (void *)&lcmd, sizeof(load_command)) != sizeof(load_command)) {
   6.770 +      goto err;
   6.771 +    }
   6.772 +    offset += lcmd.cmdsize;    // next command position
   6.773 +    if (lcmd.cmd == LC_SEGMENT_64) {
   6.774 +      lseek(fd, -sizeof(load_command), SEEK_CUR);
   6.775 +      if (read(fd, (void *)&segcmd, sizeof(segment_command_64)) != sizeof(segment_command_64)) {
   6.776 +        print_debug("failed to read LC_SEGMENT_64 i = %d!\n", i);
   6.777 +        goto err;
   6.778 +      }
   6.779 +      if (add_map_info(ph, fd, segcmd.fileoff, segcmd.vmaddr, segcmd.vmsize) == NULL) {
   6.780 +        print_debug("Failed to add map_info at i = %d\n", i);
   6.781 +        goto err;
   6.782 +      }
   6.783 +      print_debug("segment added: %" PRIu64 " 0x%" PRIx64 " %d\n",
   6.784 +                   segcmd.fileoff, segcmd.vmaddr, segcmd.vmsize);
   6.785 +    } else if (lcmd.cmd == LC_THREAD || lcmd.cmd == LC_UNIXTHREAD) {
   6.786 +      typedef struct thread_fc {
   6.787 +        uint32_t  flavor;
   6.788 +        uint32_t  count;
   6.789 +      } thread_fc;
   6.790 +      thread_fc fc;
   6.791 +      uint32_t size = sizeof(load_command);
   6.792 +      while (size < lcmd.cmdsize) {
   6.793 +        if (read(fd, (void *)&fc, sizeof(thread_fc)) != sizeof(thread_fc)) {
   6.794 +          printf("Reading flavor, count failed.\n");
   6.795 +          goto err;
   6.796 +        }
   6.797 +        size += sizeof(thread_fc);
   6.798 +        if (fc.flavor == x86_THREAD_STATE) {
   6.799 +          x86_thread_state_t thrstate;
   6.800 +          if (read(fd, (void *)&thrstate, sizeof(x86_thread_state_t)) != sizeof(x86_thread_state_t)) {
   6.801 +            printf("Reading flavor, count failed.\n");
   6.802 +            goto err;
   6.803 +          }
   6.804 +          size += sizeof(x86_thread_state_t);
   6.805 +          // create thread info list, update lwp_id later
   6.806 +          sa_thread_info* newthr = add_thread_info(ph, (pthread_t) -1, (lwpid_t) num_threads++);
   6.807 +          if (newthr == NULL) {
   6.808 +            printf("create thread_info failed\n");
   6.809 +            goto err;
   6.810 +          }
   6.811 +
   6.812 +          // note __DARWIN_UNIX03 depengs on other definitions
   6.813 +#if __DARWIN_UNIX03
   6.814 +#define get_register_v(regst, regname) \
   6.815 +  regst.uts.ts64.__##regname
   6.816 +#else
   6.817 +#define get_register_v(regst, regname) \
   6.818 +  regst.uts.ts64.##regname
   6.819 +#endif // __DARWIN_UNIX03
   6.820 +          newthr->regs.r_rax = get_register_v(thrstate, rax);
   6.821 +          newthr->regs.r_rbx = get_register_v(thrstate, rbx);
   6.822 +          newthr->regs.r_rcx = get_register_v(thrstate, rcx);
   6.823 +          newthr->regs.r_rdx = get_register_v(thrstate, rdx);
   6.824 +          newthr->regs.r_rdi = get_register_v(thrstate, rdi);
   6.825 +          newthr->regs.r_rsi = get_register_v(thrstate, rsi);
   6.826 +          newthr->regs.r_rbp = get_register_v(thrstate, rbp);
   6.827 +          newthr->regs.r_rsp = get_register_v(thrstate, rsp);
   6.828 +          newthr->regs.r_r8  = get_register_v(thrstate, r8);
   6.829 +          newthr->regs.r_r9  = get_register_v(thrstate, r9);
   6.830 +          newthr->regs.r_r10 = get_register_v(thrstate, r10);
   6.831 +          newthr->regs.r_r11 = get_register_v(thrstate, r11);
   6.832 +          newthr->regs.r_r12 = get_register_v(thrstate, r12);
   6.833 +          newthr->regs.r_r13 = get_register_v(thrstate, r13);
   6.834 +          newthr->regs.r_r14 = get_register_v(thrstate, r14);
   6.835 +          newthr->regs.r_r15 = get_register_v(thrstate, r15);
   6.836 +          newthr->regs.r_rip = get_register_v(thrstate, rip);
   6.837 +          newthr->regs.r_rflags = get_register_v(thrstate, rflags);
   6.838 +          newthr->regs.r_cs  = get_register_v(thrstate, cs);
   6.839 +          newthr->regs.r_fs  = get_register_v(thrstate, fs);
   6.840 +          newthr->regs.r_gs  = get_register_v(thrstate, gs);
   6.841 +          print_thread(newthr);
   6.842 +        } else if (fc.flavor == x86_FLOAT_STATE) {
   6.843 +          x86_float_state_t flstate;
   6.844 +          if (read(fd, (void *)&flstate, sizeof(x86_float_state_t)) != sizeof(x86_float_state_t)) {
   6.845 +            print_debug("Reading flavor, count failed.\n");
   6.846 +            goto err;
   6.847 +          }
   6.848 +          size += sizeof(x86_float_state_t);
   6.849 +        } else if (fc.flavor == x86_EXCEPTION_STATE) {
   6.850 +          x86_exception_state_t excpstate;
   6.851 +          if (read(fd, (void *)&excpstate, sizeof(x86_exception_state_t)) != sizeof(x86_exception_state_t)) {
   6.852 +            printf("Reading flavor, count failed.\n");
   6.853 +            goto err;
   6.854 +          }
   6.855 +          size += sizeof(x86_exception_state_t);
   6.856 +        }
   6.857 +      }
   6.858 +    }
   6.859 +  }
   6.860 +  return true;
   6.861 +err:
   6.862 +  return false;
   6.863 +}
   6.864 +
   6.865 +/**local function **/
   6.866 +bool exists(const char *fname)
   6.867 +{
   6.868 +  int fd;
   6.869 +  if ((fd = open(fname, O_RDONLY)) > 0) {
   6.870 +    close(fd);
   6.871 +    return true;
   6.872 +  }
   6.873 +  return false;
   6.874 +}
   6.875 +
   6.876 +// we check: 1. lib
   6.877 +//           2. lib/server
   6.878 +//           3. jre/lib
   6.879 +//           4. jre/lib/server
   6.880 +// from: 1. exe path
   6.881 +//       2. JAVA_HOME
   6.882 +//       3. DYLD_LIBRARY_PATH
   6.883 +static bool get_real_path(struct ps_prochandle* ph, char *rpath) {
   6.884 +  /** check if they exist in JAVA ***/
   6.885 +  char* execname = ph->core->exec_path;
   6.886 +  char  filepath[4096];
   6.887 +  char* filename = strrchr(rpath, '/');               // like /libjvm.dylib
   6.888 +  if (filename == NULL) {
   6.889 +    return false;
   6.890 +  }
   6.891 +
   6.892 +  char* posbin = strstr(execname, "/bin/java");
   6.893 +  if (posbin != NULL) {
   6.894 +    memcpy(filepath, execname, posbin - execname);    // not include trailing '/'
   6.895 +    filepath[posbin - execname] = '\0';
   6.896 +  } else {
   6.897 +    char* java_home = getenv("JAVA_HOME");
   6.898 +    if (java_home != NULL) {
   6.899 +      strcpy(filepath, java_home);
   6.900 +    } else {
   6.901 +      char* dyldpath = getenv("DYLD_LIBRARY_PATH");
   6.902 +      char* dypath = strtok(dyldpath, ":");
   6.903 +      while (dypath != NULL) {
   6.904 +        strcpy(filepath, dypath);
   6.905 +        strcat(filepath, filename);
   6.906 +        if (exists(filepath)) {
   6.907 +           strcpy(rpath, filepath);
   6.908 +           return true;
   6.909 +        }
   6.910 +        dypath = strtok(dyldpath, ":");
   6.911 +      }
   6.912 +      // not found
   6.913 +      return false;
   6.914 +    }
   6.915 +  }
   6.916 +  // for exec and java_home, jdkpath now is filepath
   6.917 +  size_t filepath_base_size = strlen(filepath);
   6.918 +
   6.919 +  // first try /lib/ and /lib/server
   6.920 +  strcat(filepath, "/lib");
   6.921 +  strcat(filepath, filename);
   6.922 +  if (exists(filepath)) {
   6.923 +    strcpy(rpath, filepath);
   6.924 +    return true;
   6.925 +  }
   6.926 +  char* pos = strstr(filepath, filename);    // like /libjvm.dylib
   6.927 +  *pos = '\0';
   6.928 +  strcat(filepath, "/server");
   6.929 +  strcat(filepath, filename);
   6.930 +  if (exists(filepath)) {
   6.931 +    strcpy(rpath, filepath);
   6.932 +    return true;
   6.933 +  }
   6.934 +
   6.935 +  // then try /jre/lib/ and /jre/lib/server
   6.936 +  filepath[filepath_base_size] = '\0';
   6.937 +  strcat(filepath, "/jre/lib");
   6.938 +  strcat(filepath, filename);
   6.939 +  if (exists(filepath)) {
   6.940 +    strcpy(rpath, filepath);
   6.941 +    return true;
   6.942 +  }
   6.943 +  pos = strstr(filepath, filename);
   6.944 +  *pos = '\0';
   6.945 +  strcat(filepath, "/server");
   6.946 +  strcat(filepath, filename);
   6.947 +  if (exists(filepath)) {
   6.948 +    strcpy(rpath, filepath);
   6.949 +    return true;
   6.950 +  }
   6.951 +
   6.952 +  return false;
   6.953 +}
   6.954 +
   6.955 +static bool read_shared_lib_info(struct ps_prochandle* ph) {
   6.956 +  static int pagesize = 0;
   6.957 +  int fd = ph->core->core_fd;
   6.958 +  int i = 0, j;
   6.959 +  uint32_t  v;
   6.960 +  mach_header_64 header;        // used to check if a file header in segment
   6.961 +  load_command lcmd;
   6.962 +  dylib_command dylibcmd;
   6.963 +
   6.964 +  char name[BUF_SIZE];  // use to store name
   6.965 +
   6.966 +  if (pagesize == 0) {
   6.967 +    pagesize = getpagesize();
   6.968 +    print_debug("page size is %d\n", pagesize);
   6.969 +  }
   6.970 +  for (j = 0; j < ph->core->num_maps; j++) {
   6.971 +    map_info *iter = ph->core->map_array[j];   // head
   6.972 +    off_t fpos = iter->offset;
   6.973 +    if (iter->fd != fd) {
   6.974 +      // only search core file!
   6.975 +      continue;
   6.976 +    }
   6.977 +    print_debug("map_info %d: vmaddr = 0x%016" PRIx64 "  fileoff = %" PRIu64 "  vmsize = %" PRIu64 "\n",
   6.978 +                           j, iter->vaddr, iter->offset, iter->memsz);
   6.979 +    lseek(fd, fpos, SEEK_SET);
   6.980 +    // we assume .dylib loaded at segment address --- which is true for JVM libraries
   6.981 +    // multiple files may be loaded in one segment.
   6.982 +    // if first word is not a magic word, means this segment does not contain lib file.
   6.983 +    if (read(fd, (void *)&v, sizeof(uint32_t)) == sizeof(uint32_t)) {
   6.984 +      if (v != MH_MAGIC_64) {
   6.985 +        continue;
   6.986 +      }
   6.987 +    } else {
   6.988 +      // may be encountered last map, which is not readable
   6.989 +      continue;
   6.990 +    }
   6.991 +    while (ltell(fd) - iter->offset < iter->memsz) {
   6.992 +      lseek(fd, fpos, SEEK_SET);
   6.993 +      if (read(fd, (void *)&v, sizeof(uint32_t)) != sizeof(uint32_t)) {
   6.994 +        break;
   6.995 +      }
   6.996 +      if (v != MH_MAGIC_64) {
   6.997 +        fpos = (ltell(fd) + pagesize -1)/pagesize * pagesize;
   6.998 +        continue;
   6.999 +      }
  6.1000 +      lseek(fd, -sizeof(uint32_t), SEEK_CUR);
  6.1001 +      // this is the file begining to core file.
  6.1002 +      if (read(fd, (void *)&header, sizeof(mach_header_64)) != sizeof(mach_header_64)) {
  6.1003 +        goto err;
  6.1004 +      }
  6.1005 +      fpos = ltell(fd);
  6.1006 +
  6.1007 +      // found a mach-o file in this segment
  6.1008 +      for (i = 0; i < header.ncmds; i++) {
  6.1009 +        // read commands in this "file"
  6.1010 +        // LC_ID_DYLIB is the file itself for a .dylib
  6.1011 +        lseek(fd, fpos, SEEK_SET);
  6.1012 +        if (read(fd, (void *)&lcmd, sizeof(load_command)) != sizeof(load_command)) {
  6.1013 +          return false;   // error
  6.1014 +        }
  6.1015 +        fpos += lcmd.cmdsize;  // next command position
  6.1016 +        // make sure still within seg size.
  6.1017 +        if (fpos  - lcmd.cmdsize - iter->offset > iter->memsz) {
  6.1018 +          print_debug("Warning: out of segement limit: %ld \n", fpos  - lcmd.cmdsize - iter->offset);
  6.1019 +          break;  // no need to iterate all commands
  6.1020 +        }
  6.1021 +        if (lcmd.cmd == LC_ID_DYLIB) {
  6.1022 +          lseek(fd, -sizeof(load_command), SEEK_CUR);
  6.1023 +          if (read(fd, (void *)&dylibcmd, sizeof(dylib_command)) != sizeof(dylib_command)) {
  6.1024 +            return false;
  6.1025 +          }
  6.1026 +          /**** name stored at dylib_command.dylib.name.offset, is a C string  */
  6.1027 +          lseek(fd, dylibcmd.dylib.name.offset - sizeof(dylib_command), SEEK_CUR);
  6.1028 +          int j = 0;
  6.1029 +          while (j < BUF_SIZE) {
  6.1030 +            read(fd, (void *)(name + j), sizeof(char));
  6.1031 +            if (name[j] == '\0') break;
  6.1032 +            j++;
  6.1033 +          }
  6.1034 +          print_debug("%s\n", name);
  6.1035 +          // changed name from @rpath/xxxx.dylib to real path
  6.1036 +          if (strrchr(name, '@')) {
  6.1037 +            get_real_path(ph, name);
  6.1038 +            print_debug("get_real_path returned: %s\n", name);
  6.1039 +          }
  6.1040 +          add_lib_info(ph, name, iter->vaddr);
  6.1041 +          break;
  6.1042 +        }
  6.1043 +      }
  6.1044 +      // done with the file, advanced to next page to search more files
  6.1045 +      fpos = (ltell(fd) + pagesize - 1) / pagesize * pagesize;
  6.1046 +    }
  6.1047 +  }
  6.1048 +  return true;
  6.1049 +err:
  6.1050 +  return false;
  6.1051 +}
  6.1052 +
  6.1053 +bool read_macho64_header(int fd, mach_header_64* core_header) {
  6.1054 +  bool is_macho = false;
  6.1055 +  if (fd < 0) return false;
  6.1056 +  off_t pos = ltell(fd);
  6.1057 +  lseek(fd, 0, SEEK_SET);
  6.1058 +  if (read(fd, (void *)core_header, sizeof(mach_header_64)) != sizeof(mach_header_64)) {
  6.1059 +    is_macho = false;
  6.1060 +  } else {
  6.1061 +    is_macho = (core_header->magic ==  MH_MAGIC_64 || core_header->magic ==  MH_CIGAM_64);
  6.1062 +  }
  6.1063 +  lseek(fd, pos, SEEK_SET);
  6.1064 +  return is_macho;
  6.1065 +}
  6.1066 +
  6.1067 +// the one and only one exposed stuff from this file
  6.1068 +struct ps_prochandle* Pgrab_core(const char* exec_file, const char* core_file) {
  6.1069 +  mach_header_64 core_header;
  6.1070 +  mach_header_64 exec_header;
  6.1071 +
  6.1072 +  struct ps_prochandle* ph = (struct ps_prochandle*) calloc(1, sizeof(struct ps_prochandle));
  6.1073 +  if (ph == NULL) {
  6.1074 +    print_debug("cant allocate ps_prochandle\n");
  6.1075 +    return NULL;
  6.1076 +  }
  6.1077 +
  6.1078 +  if ((ph->core = (struct core_data*) calloc(1, sizeof(struct core_data))) == NULL) {
  6.1079 +    free(ph);
  6.1080 +    print_debug("can't allocate ps_prochandle\n");
  6.1081 +    return NULL;
  6.1082 +  }
  6.1083 +
  6.1084 +  // initialize ph
  6.1085 +  ph->ops = &core_ops;
  6.1086 +  ph->core->core_fd   = -1;
  6.1087 +  ph->core->exec_fd   = -1;
  6.1088 +  ph->core->interp_fd = -1;
  6.1089 +
  6.1090 +  print_debug("exec: %s   core: %s", exec_file, core_file);
  6.1091 +
  6.1092 +  strncpy(ph->core->exec_path, exec_file, sizeof(ph->core->exec_path));
  6.1093 +
  6.1094 +  // open the core file
  6.1095 +  if ((ph->core->core_fd = open(core_file, O_RDONLY)) < 0) {
  6.1096 +    print_error("can't open core file\n");
  6.1097 +    goto err;
  6.1098 +  }
  6.1099 +
  6.1100 +  // read core file header
  6.1101 +  if (read_macho64_header(ph->core->core_fd, &core_header) != true || core_header.filetype != MH_CORE) {
  6.1102 +    print_debug("core file is not a valid Mach-O file\n");
  6.1103 +    goto err;
  6.1104 +  }
  6.1105 +
  6.1106 +  if ((ph->core->exec_fd = open(exec_file, O_RDONLY)) < 0) {
  6.1107 +    print_error("can't open executable file\n");
  6.1108 +    goto err;
  6.1109 +  }
  6.1110 +
  6.1111 +  if (read_macho64_header(ph->core->exec_fd, &exec_header) != true ||
  6.1112 +                          exec_header.filetype != MH_EXECUTE) {
  6.1113 +    print_error("executable file is not a valid Mach-O file\n");
  6.1114 +    goto err;
  6.1115 +  }
  6.1116 +
  6.1117 +  // process core file segments
  6.1118 +  if (read_core_segments(ph) != true) {
  6.1119 +    print_error("failed to read core segments\n");
  6.1120 +    goto err;
  6.1121 +  }
  6.1122 +
  6.1123 +  // allocate and sort maps into map_array, we need to do this
  6.1124 +  // here because read_shared_lib_info needs to read from debuggee
  6.1125 +  // address space
  6.1126 +  if (sort_map_array(ph) != true) {
  6.1127 +    print_error("failed to sort segment map array\n");
  6.1128 +    goto err;
  6.1129 +  }
  6.1130 +
  6.1131 +  if (read_shared_lib_info(ph) != true) {
  6.1132 +    print_error("failed to read libraries\n");
  6.1133 +    goto err;
  6.1134 +  }
  6.1135 +
  6.1136 +  // sort again because we have added more mappings from shared objects
  6.1137 +  if (sort_map_array(ph) != true) {
  6.1138 +    print_error("failed to sort segment map array\n");
  6.1139 +    goto err;
  6.1140 +  }
  6.1141 +
  6.1142 +  if (init_classsharing_workaround(ph) != true) {
  6.1143 +    print_error("failed to workaround classshareing\n");
  6.1144 +    goto err;
  6.1145 +  }
  6.1146 +
  6.1147 +  print_debug("Leave Pgrab_core\n");
  6.1148 +  return ph;
  6.1149 +
  6.1150 +err:
  6.1151 +  Prelease(ph);
  6.1152 +  return NULL;
  6.1153 +}
  6.1154 +
  6.1155 +#else // __APPLE__ (none macosx)
  6.1156 +
  6.1157 +// read regs and create thread from core file
  6.1158  static bool core_handle_prstatus(struct ps_prochandle* ph, const char* buf, size_t nbytes) {
  6.1159     // we have to read prstatus_t from buf
  6.1160     // assert(nbytes == sizeof(prstaus_t), "size mismatch on prstatus_t");
  6.1161     prstatus_t* prstat = (prstatus_t*) buf;
  6.1162 -   thread_info* newthr;
  6.1163 +   sa_thread_info* newthr;
  6.1164     print_debug("got integer regset for lwp %d\n", prstat->pr_pid);
  6.1165     // we set pthread_t to -1 for core dump
  6.1166     if((newthr = add_thread_info(ph, (pthread_t) -1,  prstat->pr_pid)) == NULL)
  6.1167 @@ -632,8 +1093,9 @@
  6.1168                                     notep->n_type, notep->n_descsz);
  6.1169  
  6.1170        if (notep->n_type == NT_PRSTATUS) {
  6.1171 -         if (core_handle_prstatus(ph, descdata, notep->n_descsz) != true)
  6.1172 +         if (core_handle_prstatus(ph, descdata, notep->n_descsz) != true) {
  6.1173              return false;
  6.1174 +         }
  6.1175        }
  6.1176        p = descdata + ROUNDUP(notep->n_descsz, 4);
  6.1177     }
  6.1178 @@ -681,7 +1143,9 @@
  6.1179      for (core_php = phbuf, i = 0; i < core_ehdr->e_phnum; i++) {
  6.1180        switch (core_php->p_type) {
  6.1181           case PT_NOTE:
  6.1182 -            if (core_handle_note(ph, core_php) != true) goto err;
  6.1183 +            if (core_handle_note(ph, core_php) != true) {
  6.1184 +              goto err;
  6.1185 +            }
  6.1186              break;
  6.1187  
  6.1188           case PT_LOAD: {
  6.1189 @@ -800,7 +1264,6 @@
  6.1190     return false;
  6.1191  }
  6.1192  
  6.1193 -
  6.1194  #define FIRST_LINK_MAP_OFFSET offsetof(struct r_debug,  r_map)
  6.1195  #define LD_BASE_OFFSET        offsetof(struct r_debug,  r_ldbase)
  6.1196  #define LINK_MAP_ADDR_OFFSET  offsetof(struct link_map, l_addr)
  6.1197 @@ -810,213 +1273,218 @@
  6.1198  // read shared library info from runtime linker's data structures.
  6.1199  // This work is done by librtlb_db in Solaris
  6.1200  static bool read_shared_lib_info(struct ps_prochandle* ph) {
  6.1201 -   uintptr_t addr = ph->core->dynamic_addr;
  6.1202 -   uintptr_t debug_base;
  6.1203 -   uintptr_t first_link_map_addr;
  6.1204 -   uintptr_t ld_base_addr;
  6.1205 -   uintptr_t link_map_addr;
  6.1206 -   uintptr_t lib_base_diff;
  6.1207 -   uintptr_t lib_base;
  6.1208 -   uintptr_t lib_name_addr;
  6.1209 -   char lib_name[BUF_SIZE];
  6.1210 -   ELF_DYN dyn;
  6.1211 -   ELF_EHDR elf_ehdr;
  6.1212 -   int lib_fd;
  6.1213 +  uintptr_t addr = ph->core->dynamic_addr;
  6.1214 +  uintptr_t debug_base;
  6.1215 +  uintptr_t first_link_map_addr;
  6.1216 +  uintptr_t ld_base_addr;
  6.1217 +  uintptr_t link_map_addr;
  6.1218 +  uintptr_t lib_base_diff;
  6.1219 +  uintptr_t lib_base;
  6.1220 +  uintptr_t lib_name_addr;
  6.1221 +  char lib_name[BUF_SIZE];
  6.1222 +  ELF_DYN dyn;
  6.1223 +  ELF_EHDR elf_ehdr;
  6.1224 +  int lib_fd;
  6.1225  
  6.1226 -   // _DYNAMIC has information of the form
  6.1227 -   //         [tag] [data] [tag] [data] .....
  6.1228 -   // Both tag and data are pointer sized.
  6.1229 -   // We look for dynamic info with DT_DEBUG. This has shared object info.
  6.1230 -   // refer to struct r_debug in link.h
  6.1231 +  // _DYNAMIC has information of the form
  6.1232 +  //         [tag] [data] [tag] [data] .....
  6.1233 +  // Both tag and data are pointer sized.
  6.1234 +  // We look for dynamic info with DT_DEBUG. This has shared object info.
  6.1235 +  // refer to struct r_debug in link.h
  6.1236  
  6.1237 -   dyn.d_tag = DT_NULL;
  6.1238 -   while (dyn.d_tag != DT_DEBUG) {
  6.1239 -      if (ps_pread(ph, (psaddr_t) addr, &dyn, sizeof(ELF_DYN)) != PS_OK) {
  6.1240 -         print_debug("can't read debug info from _DYNAMIC\n");
  6.1241 -         return false;
  6.1242 +  dyn.d_tag = DT_NULL;
  6.1243 +  while (dyn.d_tag != DT_DEBUG) {
  6.1244 +    if (ps_pread(ph, (psaddr_t) addr, &dyn, sizeof(ELF_DYN)) != PS_OK) {
  6.1245 +      print_debug("can't read debug info from _DYNAMIC\n");
  6.1246 +      return false;
  6.1247 +    }
  6.1248 +    addr += sizeof(ELF_DYN);
  6.1249 +  }
  6.1250 +
  6.1251 +  // we have got Dyn entry with DT_DEBUG
  6.1252 +  debug_base = dyn.d_un.d_ptr;
  6.1253 +  // at debug_base we have struct r_debug. This has first link map in r_map field
  6.1254 +  if (ps_pread(ph, (psaddr_t) debug_base + FIRST_LINK_MAP_OFFSET,
  6.1255 +                  &first_link_map_addr, sizeof(uintptr_t)) != PS_OK) {
  6.1256 +    print_debug("can't read first link map address\n");
  6.1257 +    return false;
  6.1258 +  }
  6.1259 +
  6.1260 +  // read ld_base address from struct r_debug
  6.1261 +  // XXX: There is no r_ldbase member on BSD
  6.1262 +  /*
  6.1263 +  if (ps_pread(ph, (psaddr_t) debug_base + LD_BASE_OFFSET, &ld_base_addr,
  6.1264 +                  sizeof(uintptr_t)) != PS_OK) {
  6.1265 +    print_debug("can't read ld base address\n");
  6.1266 +    return false;
  6.1267 +  }
  6.1268 +  ph->core->ld_base_addr = ld_base_addr;
  6.1269 +  */
  6.1270 +  ph->core->ld_base_addr = 0;
  6.1271 +
  6.1272 +  print_debug("interpreter base address is 0x%lx\n", ld_base_addr);
  6.1273 +
  6.1274 +  // now read segments from interp (i.e ld-elf.so.1)
  6.1275 +  if (read_interp_segments(ph) != true)
  6.1276 +    return false;
  6.1277 +
  6.1278 +  // after adding interpreter (ld.so) mappings sort again
  6.1279 +  if (sort_map_array(ph) != true)
  6.1280 +    return false;
  6.1281 +
  6.1282 +  print_debug("first link map is at 0x%lx\n", first_link_map_addr);
  6.1283 +
  6.1284 +  link_map_addr = first_link_map_addr;
  6.1285 +  while (link_map_addr != 0) {
  6.1286 +    // read library base address of the .so. Note that even though <sys/link.h> calls
  6.1287 +    // link_map->l_addr as "base address",  this is * not * really base virtual
  6.1288 +    // address of the shared object. This is actually the difference b/w the virtual
  6.1289 +    // address mentioned in shared object and the actual virtual base where runtime
  6.1290 +    // linker loaded it. We use "base diff" in read_lib_segments call below.
  6.1291 +
  6.1292 +    if (ps_pread(ph, (psaddr_t) link_map_addr + LINK_MAP_ADDR_OFFSET,
  6.1293 +                 &lib_base_diff, sizeof(uintptr_t)) != PS_OK) {
  6.1294 +      print_debug("can't read shared object base address diff\n");
  6.1295 +      return false;
  6.1296 +    }
  6.1297 +
  6.1298 +    // read address of the name
  6.1299 +    if (ps_pread(ph, (psaddr_t) link_map_addr + LINK_MAP_NAME_OFFSET,
  6.1300 +                  &lib_name_addr, sizeof(uintptr_t)) != PS_OK) {
  6.1301 +      print_debug("can't read address of shared object name\n");
  6.1302 +      return false;
  6.1303 +    }
  6.1304 +
  6.1305 +    // read name of the shared object
  6.1306 +    if (read_string(ph, (uintptr_t) lib_name_addr, lib_name, sizeof(lib_name)) != true) {
  6.1307 +      print_debug("can't read shared object name\n");
  6.1308 +      return false;
  6.1309 +    }
  6.1310 +
  6.1311 +    if (lib_name[0] != '\0') {
  6.1312 +      // ignore empty lib names
  6.1313 +      lib_fd = pathmap_open(lib_name);
  6.1314 +
  6.1315 +      if (lib_fd < 0) {
  6.1316 +        print_debug("can't open shared object %s\n", lib_name);
  6.1317 +        // continue with other libraries...
  6.1318 +      } else {
  6.1319 +        if (read_elf_header(lib_fd, &elf_ehdr)) {
  6.1320 +          lib_base = lib_base_diff + find_base_address(lib_fd, &elf_ehdr);
  6.1321 +          print_debug("reading library %s @ 0x%lx [ 0x%lx ]\n",
  6.1322 +                       lib_name, lib_base, lib_base_diff);
  6.1323 +          // while adding library mappings we need to use "base difference".
  6.1324 +          if (! read_lib_segments(ph, lib_fd, &elf_ehdr, lib_base_diff)) {
  6.1325 +            print_debug("can't read shared object's segments\n");
  6.1326 +            close(lib_fd);
  6.1327 +            return false;
  6.1328 +          }
  6.1329 +          add_lib_info_fd(ph, lib_name, lib_fd, lib_base);
  6.1330 +          // Map info is added for the library (lib_name) so
  6.1331 +          // we need to re-sort it before calling the p_pdread.
  6.1332 +          if (sort_map_array(ph) != true)
  6.1333 +            return false;
  6.1334 +        } else {
  6.1335 +          print_debug("can't read ELF header for shared object %s\n", lib_name);
  6.1336 +          close(lib_fd);
  6.1337 +          // continue with other libraries...
  6.1338 +        }
  6.1339        }
  6.1340 -      addr += sizeof(ELF_DYN);
  6.1341 -   }
  6.1342 +    }
  6.1343  
  6.1344 -   // we have got Dyn entry with DT_DEBUG
  6.1345 -   debug_base = dyn.d_un.d_ptr;
  6.1346 -   // at debug_base we have struct r_debug. This has first link map in r_map field
  6.1347 -   if (ps_pread(ph, (psaddr_t) debug_base + FIRST_LINK_MAP_OFFSET,
  6.1348 -                 &first_link_map_addr, sizeof(uintptr_t)) != PS_OK) {
  6.1349 -      print_debug("can't read first link map address\n");
  6.1350 +    // read next link_map address
  6.1351 +    if (ps_pread(ph, (psaddr_t) link_map_addr + LINK_MAP_NEXT_OFFSET,
  6.1352 +                 &link_map_addr, sizeof(uintptr_t)) != PS_OK) {
  6.1353 +      print_debug("can't read next link in link_map\n");
  6.1354        return false;
  6.1355 -   }
  6.1356 +    }
  6.1357 +  }
  6.1358  
  6.1359 -   // read ld_base address from struct r_debug
  6.1360 -   // XXX: There is no r_ldbase member on BSD
  6.1361 -/*
  6.1362 -   if (ps_pread(ph, (psaddr_t) debug_base + LD_BASE_OFFSET, &ld_base_addr,
  6.1363 -                 sizeof(uintptr_t)) != PS_OK) {
  6.1364 -      print_debug("can't read ld base address\n");
  6.1365 -      return false;
  6.1366 -   }
  6.1367 -   ph->core->ld_base_addr = ld_base_addr;
  6.1368 -*/
  6.1369 -   ph->core->ld_base_addr = 0;
  6.1370 -
  6.1371 -   print_debug("interpreter base address is 0x%lx\n", ld_base_addr);
  6.1372 -
  6.1373 -   // now read segments from interp (i.e ld-elf.so.1)
  6.1374 -   if (read_interp_segments(ph) != true)
  6.1375 -      return false;
  6.1376 -
  6.1377 -   // after adding interpreter (ld.so) mappings sort again
  6.1378 -   if (sort_map_array(ph) != true)
  6.1379 -      return false;
  6.1380 -
  6.1381 -   print_debug("first link map is at 0x%lx\n", first_link_map_addr);
  6.1382 -
  6.1383 -   link_map_addr = first_link_map_addr;
  6.1384 -   while (link_map_addr != 0) {
  6.1385 -      // read library base address of the .so. Note that even though <sys/link.h> calls
  6.1386 -      // link_map->l_addr as "base address",  this is * not * really base virtual
  6.1387 -      // address of the shared object. This is actually the difference b/w the virtual
  6.1388 -      // address mentioned in shared object and the actual virtual base where runtime
  6.1389 -      // linker loaded it. We use "base diff" in read_lib_segments call below.
  6.1390 -
  6.1391 -      if (ps_pread(ph, (psaddr_t) link_map_addr + LINK_MAP_ADDR_OFFSET,
  6.1392 -                   &lib_base_diff, sizeof(uintptr_t)) != PS_OK) {
  6.1393 -         print_debug("can't read shared object base address diff\n");
  6.1394 -         return false;
  6.1395 -      }
  6.1396 -
  6.1397 -      // read address of the name
  6.1398 -      if (ps_pread(ph, (psaddr_t) link_map_addr + LINK_MAP_NAME_OFFSET,
  6.1399 -                    &lib_name_addr, sizeof(uintptr_t)) != PS_OK) {
  6.1400 -         print_debug("can't read address of shared object name\n");
  6.1401 -         return false;
  6.1402 -      }
  6.1403 -
  6.1404 -      // read name of the shared object
  6.1405 -      if (read_string(ph, (uintptr_t) lib_name_addr, lib_name, sizeof(lib_name)) != true) {
  6.1406 -         print_debug("can't read shared object name\n");
  6.1407 -         return false;
  6.1408 -      }
  6.1409 -
  6.1410 -      if (lib_name[0] != '\0') {
  6.1411 -         // ignore empty lib names
  6.1412 -         lib_fd = pathmap_open(lib_name);
  6.1413 -
  6.1414 -         if (lib_fd < 0) {
  6.1415 -            print_debug("can't open shared object %s\n", lib_name);
  6.1416 -            // continue with other libraries...
  6.1417 -         } else {
  6.1418 -            if (read_elf_header(lib_fd, &elf_ehdr)) {
  6.1419 -               lib_base = lib_base_diff + find_base_address(lib_fd, &elf_ehdr);
  6.1420 -               print_debug("reading library %s @ 0x%lx [ 0x%lx ]\n",
  6.1421 -                           lib_name, lib_base, lib_base_diff);
  6.1422 -               // while adding library mappings we need to use "base difference".
  6.1423 -               if (! read_lib_segments(ph, lib_fd, &elf_ehdr, lib_base_diff)) {
  6.1424 -                  print_debug("can't read shared object's segments\n");
  6.1425 -                  close(lib_fd);
  6.1426 -                  return false;
  6.1427 -               }
  6.1428 -               add_lib_info_fd(ph, lib_name, lib_fd, lib_base);
  6.1429 -               // Map info is added for the library (lib_name) so
  6.1430 -               // we need to re-sort it before calling the p_pdread.
  6.1431 -               if (sort_map_array(ph) != true)
  6.1432 -                  return false;
  6.1433 -            } else {
  6.1434 -               print_debug("can't read ELF header for shared object %s\n", lib_name);
  6.1435 -               close(lib_fd);
  6.1436 -               // continue with other libraries...
  6.1437 -            }
  6.1438 -         }
  6.1439 -      }
  6.1440 -
  6.1441 -      // read next link_map address
  6.1442 -      if (ps_pread(ph, (psaddr_t) link_map_addr + LINK_MAP_NEXT_OFFSET,
  6.1443 -                        &link_map_addr, sizeof(uintptr_t)) != PS_OK) {
  6.1444 -         print_debug("can't read next link in link_map\n");
  6.1445 -         return false;
  6.1446 -      }
  6.1447 -   }
  6.1448 -
  6.1449 -   return true;
  6.1450 +  return true;
  6.1451  }
  6.1452  
  6.1453  // the one and only one exposed stuff from this file
  6.1454  struct ps_prochandle* Pgrab_core(const char* exec_file, const char* core_file) {
  6.1455 -   ELF_EHDR core_ehdr;
  6.1456 -   ELF_EHDR exec_ehdr;
  6.1457 +  ELF_EHDR core_ehdr;
  6.1458 +  ELF_EHDR exec_ehdr;
  6.1459  
  6.1460 -   struct ps_prochandle* ph = (struct ps_prochandle*) calloc(1, sizeof(struct ps_prochandle));
  6.1461 -   if (ph == NULL) {
  6.1462 -      print_debug("can't allocate ps_prochandle\n");
  6.1463 -      return NULL;
  6.1464 -   }
  6.1465 +  struct ps_prochandle* ph = (struct ps_prochandle*) calloc(1, sizeof(struct ps_prochandle));
  6.1466 +  if (ph == NULL) {
  6.1467 +    print_debug("cant allocate ps_prochandle\n");
  6.1468 +    return NULL;
  6.1469 +  }
  6.1470  
  6.1471 -   if ((ph->core = (struct core_data*) calloc(1, sizeof(struct core_data))) == NULL) {
  6.1472 -      free(ph);
  6.1473 -      print_debug("can't allocate ps_prochandle\n");
  6.1474 -      return NULL;
  6.1475 -   }
  6.1476 +  if ((ph->core = (struct core_data*) calloc(1, sizeof(struct core_data))) == NULL) {
  6.1477 +    free(ph);
  6.1478 +    print_debug("can't allocate ps_prochandle\n");
  6.1479 +    return NULL;
  6.1480 +  }
  6.1481  
  6.1482 -   // initialize ph
  6.1483 -   ph->ops = &core_ops;
  6.1484 -   ph->core->core_fd   = -1;
  6.1485 -   ph->core->exec_fd   = -1;
  6.1486 -   ph->core->interp_fd = -1;
  6.1487 +  // initialize ph
  6.1488 +  ph->ops = &core_ops;
  6.1489 +  ph->core->core_fd   = -1;
  6.1490 +  ph->core->exec_fd   = -1;
  6.1491 +  ph->core->interp_fd = -1;
  6.1492  
  6.1493 -   // open the core file
  6.1494 -   if ((ph->core->core_fd = open(core_file, O_RDONLY)) < 0) {
  6.1495 -      print_debug("can't open core file\n");
  6.1496 -      goto err;
  6.1497 -   }
  6.1498 +  print_debug("exec: %s   core: %s", exec_file, core_file);
  6.1499  
  6.1500 -   // read core file ELF header
  6.1501 -   if (read_elf_header(ph->core->core_fd, &core_ehdr) != true || core_ehdr.e_type != ET_CORE) {
  6.1502 -      print_debug("core file is not a valid ELF ET_CORE file\n");
  6.1503 -      goto err;
  6.1504 -   }
  6.1505 +  // open the core file
  6.1506 +  if ((ph->core->core_fd = open(core_file, O_RDONLY)) < 0) {
  6.1507 +    print_debug("can't open core file\n");
  6.1508 +    goto err;
  6.1509 +  }
  6.1510  
  6.1511 -   if ((ph->core->exec_fd = open(exec_file, O_RDONLY)) < 0) {
  6.1512 -      print_debug("can't open executable file\n");
  6.1513 -      goto err;
  6.1514 -   }
  6.1515 +  // read core file ELF header
  6.1516 +  if (read_elf_header(ph->core->core_fd, &core_ehdr) != true || core_ehdr.e_type != ET_CORE) {
  6.1517 +    print_debug("core file is not a valid ELF ET_CORE file\n");
  6.1518 +    goto err;
  6.1519 +  }
  6.1520  
  6.1521 -   if (read_elf_header(ph->core->exec_fd, &exec_ehdr) != true || exec_ehdr.e_type != ET_EXEC) {
  6.1522 -      print_debug("executable file is not a valid ELF ET_EXEC file\n");
  6.1523 -      goto err;
  6.1524 -   }
  6.1525 +  if ((ph->core->exec_fd = open(exec_file, O_RDONLY)) < 0) {
  6.1526 +    print_debug("can't open executable file\n");
  6.1527 +    goto err;
  6.1528 +  }
  6.1529  
  6.1530 -   // process core file segments
  6.1531 -   if (read_core_segments(ph, &core_ehdr) != true)
  6.1532 -      goto err;
  6.1533 +  if (read_elf_header(ph->core->exec_fd, &exec_ehdr) != true || exec_ehdr.e_type != ET_EXEC) {
  6.1534 +     print_debug("executable file is not a valid ELF ET_EXEC file\n");
  6.1535 +     goto err;
  6.1536 +  }
  6.1537  
  6.1538 -   // process exec file segments
  6.1539 -   if (read_exec_segments(ph, &exec_ehdr) != true)
  6.1540 -      goto err;
  6.1541 +  // process core file segments
  6.1542 +  if (read_core_segments(ph, &core_ehdr) != true)
  6.1543 +     goto err;
  6.1544  
  6.1545 -   // exec file is also treated like a shared object for symbol search
  6.1546 -   if (add_lib_info_fd(ph, exec_file, ph->core->exec_fd,
  6.1547 -                       (uintptr_t)0 + find_base_address(ph->core->exec_fd, &exec_ehdr)) == NULL)
  6.1548 -      goto err;
  6.1549 +  // process exec file segments
  6.1550 +  if (read_exec_segments(ph, &exec_ehdr) != true)
  6.1551 +     goto err;
  6.1552  
  6.1553 -   // allocate and sort maps into map_array, we need to do this
  6.1554 -   // here because read_shared_lib_info needs to read from debuggee
  6.1555 -   // address space
  6.1556 -   if (sort_map_array(ph) != true)
  6.1557 -      goto err;
  6.1558 +  // exec file is also treated like a shared object for symbol search
  6.1559 +  if (add_lib_info_fd(ph, exec_file, ph->core->exec_fd,
  6.1560 +                      (uintptr_t)0 + find_base_address(ph->core->exec_fd, &exec_ehdr)) == NULL)
  6.1561 +     goto err;
  6.1562  
  6.1563 -   if (read_shared_lib_info(ph) != true)
  6.1564 -      goto err;
  6.1565 +  // allocate and sort maps into map_array, we need to do this
  6.1566 +  // here because read_shared_lib_info needs to read from debuggee
  6.1567 +  // address space
  6.1568 +  if (sort_map_array(ph) != true)
  6.1569 +    goto err;
  6.1570  
  6.1571 -   // sort again because we have added more mappings from shared objects
  6.1572 -   if (sort_map_array(ph) != true)
  6.1573 -      goto err;
  6.1574 +  if (read_shared_lib_info(ph) != true)
  6.1575 +    goto err;
  6.1576  
  6.1577 -   if (init_classsharing_workaround(ph) != true)
  6.1578 -      goto err;
  6.1579 +  // sort again because we have added more mappings from shared objects
  6.1580 +  if (sort_map_array(ph) != true)
  6.1581 +    goto err;
  6.1582  
  6.1583 -   return ph;
  6.1584 +  if (init_classsharing_workaround(ph) != true)
  6.1585 +    goto err;
  6.1586 +
  6.1587 +  print_debug("Leave Pgrab_core\n");
  6.1588 +  return ph;
  6.1589  
  6.1590  err:
  6.1591 -   Prelease(ph);
  6.1592 -   return NULL;
  6.1593 +  Prelease(ph);
  6.1594 +  return NULL;
  6.1595  }
  6.1596 +
  6.1597 +#endif // __APPLE__
     7.1 --- a/agent/src/os/bsd/symtab.c	Fri Mar 15 11:44:33 2013 -0700
     7.2 +++ b/agent/src/os/bsd/symtab.c	Sun Mar 17 08:57:56 2013 -0700
     7.3 @@ -1,5 +1,5 @@
     7.4  /*
     7.5 - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
     7.6 + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
     7.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     7.8   *
     7.9   * This code is free software; you can redistribute it and/or modify it
    7.10 @@ -28,32 +28,182 @@
    7.11  #include <string.h>
    7.12  #include <db.h>
    7.13  #include <fcntl.h>
    7.14 +
    7.15 +#include "libproc_impl.h"
    7.16  #include "symtab.h"
    7.17 +#ifndef __APPLE__
    7.18  #include "salibelf.h"
    7.19 +#endif // __APPLE__
    7.20  
    7.21  
    7.22  // ----------------------------------------------------
    7.23  // functions for symbol lookups
    7.24  // ----------------------------------------------------
    7.25  
    7.26 +typedef struct symtab_symbol {
    7.27 +  char *name;                // name like __ZThread_...
    7.28 +  uintptr_t offset;          // to loaded address
    7.29 +  uintptr_t size;            // size strlen
    7.30 +} symtab_symbol;
    7.31 +
    7.32 +typedef struct symtab {
    7.33 +  char *strs;                // all symbols "__symbol1__'\0'__symbol2__...."
    7.34 +  size_t num_symbols;
    7.35 +  DB* hash_table;
    7.36 +  symtab_symbol* symbols;
    7.37 +} symtab_t;
    7.38 +
    7.39 +#ifdef __APPLE__
    7.40 +
    7.41 +void build_search_table(symtab_t *symtab) {
    7.42 +  int i;
    7.43 +  for (i = 0; i < symtab->num_symbols; i++) {
    7.44 +    DBT key, value;
    7.45 +    key.data = symtab->symbols[i].name;
    7.46 +    key.size = strlen(key.data) + 1;
    7.47 +    value.data = &(symtab->symbols[i]);
    7.48 +    value.size = sizeof(symtab_symbol);
    7.49 +    (*symtab->hash_table->put)(symtab->hash_table, &key, &value, 0);
    7.50 +
    7.51 +    // check result
    7.52 +    if (is_debug()) {
    7.53 +      DBT rkey, rvalue;
    7.54 +      char* tmp = (char *)malloc(strlen(symtab->symbols[i].name) + 1);
    7.55 +      strcpy(tmp, symtab->symbols[i].name);
    7.56 +      rkey.data = tmp;
    7.57 +      rkey.size = strlen(tmp) + 1;
    7.58 +      (*symtab->hash_table->get)(symtab->hash_table, &rkey, &rvalue, 0);
    7.59 +      // we may get a copy back so compare contents
    7.60 +      symtab_symbol *res = (symtab_symbol *)rvalue.data;
    7.61 +      if (strcmp(res->name, symtab->symbols[i].name)  ||
    7.62 +          res->offset != symtab->symbols[i].offset    ||
    7.63 +          res->size != symtab->symbols[i].size) {
    7.64 +        print_debug("error to get hash_table value!\n");
    7.65 +      }
    7.66 +      free(tmp);
    7.67 +    }
    7.68 +  }
    7.69 +}
    7.70 +
    7.71 +// read symbol table from given fd.
    7.72 +struct symtab* build_symtab(int fd) {
    7.73 +  symtab_t* symtab = NULL;
    7.74 +  int i;
    7.75 +  mach_header_64 header;
    7.76 +  off_t image_start;
    7.77 +
    7.78 +  if (!get_arch_off(fd, CPU_TYPE_X86_64, &image_start)) {
    7.79 +    print_debug("failed in get fat header\n");
    7.80 +    return NULL;
    7.81 +  }
    7.82 +  lseek(fd, image_start, SEEK_SET);
    7.83 +  if (read(fd, (void *)&header, sizeof(mach_header_64)) != sizeof(mach_header_64)) {
    7.84 +    print_debug("reading header failed!\n");
    7.85 +    return NULL;
    7.86 +  }
    7.87 +  // header
    7.88 +  if (header.magic != MH_MAGIC_64) {
    7.89 +    print_debug("not a valid .dylib file\n");
    7.90 +    return NULL;
    7.91 +  }
    7.92 +
    7.93 +  load_command lcmd;
    7.94 +  symtab_command symtabcmd;
    7.95 +  nlist_64 lentry;
    7.96 +
    7.97 +  bool lcsymtab_exist = false;
    7.98 +
    7.99 +  long filepos = ltell(fd);
   7.100 +  for (i = 0; i < header.ncmds; i++) {
   7.101 +    lseek(fd, filepos, SEEK_SET);
   7.102 +    if (read(fd, (void *)&lcmd, sizeof(load_command)) != sizeof(load_command)) {
   7.103 +      print_debug("read load_command failed for file\n");
   7.104 +      return NULL;
   7.105 +    }
   7.106 +    filepos += lcmd.cmdsize;  // next command position
   7.107 +    if (lcmd.cmd == LC_SYMTAB) {
   7.108 +      lseek(fd, -sizeof(load_command), SEEK_CUR);
   7.109 +      lcsymtab_exist = true;
   7.110 +      break;
   7.111 +    }
   7.112 +  }
   7.113 +  if (!lcsymtab_exist) {
   7.114 +    print_debug("No symtab command found!\n");
   7.115 +    return NULL;
   7.116 +  }
   7.117 +  if (read(fd, (void *)&symtabcmd, sizeof(symtab_command)) != sizeof(symtab_command)) {
   7.118 +    print_debug("read symtab_command failed for file");
   7.119 +    return NULL;
   7.120 +  }
   7.121 +  symtab = (symtab_t *)malloc(sizeof(symtab_t));
   7.122 +  if (symtab == NULL) {
   7.123 +    print_debug("out of memory: allocating symtab\n");
   7.124 +    return NULL;
   7.125 +  }
   7.126 +
   7.127 +  // create hash table, we use berkeley db to
   7.128 +  // manipulate the hash table.
   7.129 +  symtab->hash_table = dbopen(NULL, O_CREAT | O_RDWR, 0600, DB_HASH, NULL);
   7.130 +  if (symtab->hash_table == NULL)
   7.131 +    goto quit;
   7.132 +
   7.133 +  symtab->num_symbols = symtabcmd.nsyms;
   7.134 +  symtab->symbols = (symtab_symbol *)malloc(sizeof(symtab_symbol) * symtab->num_symbols);
   7.135 +  symtab->strs    = (char *)malloc(sizeof(char) * symtabcmd.strsize);
   7.136 +  if (symtab->symbols == NULL || symtab->strs == NULL) {
   7.137 +     print_debug("out of memory: allocating symtab.symbol or symtab.strs\n");
   7.138 +     goto quit;
   7.139 +  }
   7.140 +  lseek(fd, image_start + symtabcmd.symoff, SEEK_SET);
   7.141 +  for (i = 0; i < symtab->num_symbols; i++) {
   7.142 +    if (read(fd, (void *)&lentry, sizeof(nlist_64)) != sizeof(nlist_64)) {
   7.143 +      print_debug("read nlist_64 failed at %i\n", i);
   7.144 +      goto quit;
   7.145 +    }
   7.146 +    symtab->symbols[i].offset = lentry.n_value;
   7.147 +    symtab->symbols[i].size  = lentry.n_un.n_strx;        // index
   7.148 +  }
   7.149 +
   7.150 +  // string table
   7.151 +  lseek(fd, image_start + symtabcmd.stroff, SEEK_SET);
   7.152 +  int size = read(fd, (void *)(symtab->strs), symtabcmd.strsize * sizeof(char));
   7.153 +  if (size != symtabcmd.strsize * sizeof(char)) {
   7.154 +     print_debug("reading string table failed\n");
   7.155 +     goto quit;
   7.156 +  }
   7.157 +
   7.158 +  for (i = 0; i < symtab->num_symbols; i++) {
   7.159 +    symtab->symbols[i].name = symtab->strs + symtab->symbols[i].size;
   7.160 +    if (i > 0) {
   7.161 +      // fix size
   7.162 +      symtab->symbols[i - 1].size = symtab->symbols[i].size - symtab->symbols[i - 1].size;
   7.163 +      print_debug("%s size = %d\n", symtab->symbols[i - 1].name, symtab->symbols[i - 1].size);
   7.164 +
   7.165 +    }
   7.166 +
   7.167 +    if (i == symtab->num_symbols - 1) {
   7.168 +      // last index
   7.169 +      symtab->symbols[i].size =
   7.170 +            symtabcmd.strsize - symtab->symbols[i].size;
   7.171 +      print_debug("%s size = %d\n", symtab->symbols[i].name, symtab->symbols[i].size);
   7.172 +    }
   7.173 +  }
   7.174 +
   7.175 +  // build a hashtable for fast query
   7.176 +  build_search_table(symtab);
   7.177 +  return symtab;
   7.178 +quit:
   7.179 +  if (symtab) destroy_symtab(symtab);
   7.180 +  return NULL;
   7.181 +}
   7.182 +
   7.183 +#else // __APPLE__
   7.184 +
   7.185  struct elf_section {
   7.186    ELF_SHDR   *c_shdr;
   7.187    void       *c_data;
   7.188  };
   7.189  
   7.190 -struct elf_symbol {
   7.191 -  char *name;
   7.192 -  uintptr_t offset;
   7.193 -  uintptr_t size;
   7.194 -};
   7.195 -
   7.196 -typedef struct symtab {
   7.197 -  char *strs;
   7.198 -  size_t num_symbols;
   7.199 -  struct elf_symbol *symbols;
   7.200 -  DB* hash_table;
   7.201 -} symtab_t;
   7.202 -
   7.203  // read symbol table from given fd.
   7.204  struct symtab* build_symtab(int fd) {
   7.205    ELF_EHDR ehdr;
   7.206 @@ -176,7 +326,7 @@
   7.207          key.data = sym_name;
   7.208          key.size = strlen(sym_name) + 1;
   7.209          value.data = &(symtab->symbols[j]);
   7.210 -        value.size = sizeof(void *);
   7.211 +        value.size = sizeof(symtab_symbol);
   7.212          (*symtab->hash_table->put)(symtab->hash_table, &key, &value, 0);
   7.213        }
   7.214      }
   7.215 @@ -201,30 +351,29 @@
   7.216    return symtab;
   7.217  }
   7.218  
   7.219 -void destroy_symtab(struct symtab* symtab) {
   7.220 +#endif // __APPLE__
   7.221 +
   7.222 +void destroy_symtab(symtab_t* symtab) {
   7.223    if (!symtab) return;
   7.224 -  if (symtab->strs) free(symtab->strs);
   7.225 -  if (symtab->symbols) free(symtab->symbols);
   7.226 -  if (symtab->hash_table) {
   7.227 -    (*symtab->hash_table->close)(symtab->hash_table);
   7.228 -  }
   7.229 +  free(symtab->strs);
   7.230 +  free(symtab->symbols);
   7.231    free(symtab);
   7.232  }
   7.233  
   7.234 -uintptr_t search_symbol(struct symtab* symtab, uintptr_t base,
   7.235 -                      const char *sym_name, int *sym_size) {
   7.236 +uintptr_t search_symbol(struct symtab* symtab, uintptr_t base, const char *sym_name, int *sym_size) {
   7.237    DBT key, value;
   7.238    int ret;
   7.239  
   7.240    // library does not have symbol table
   7.241 -  if (!symtab || !symtab->hash_table)
   7.242 +  if (!symtab || !symtab->hash_table) {
   7.243       return 0;
   7.244 +  }
   7.245  
   7.246    key.data = (char*)(uintptr_t)sym_name;
   7.247    key.size = strlen(sym_name) + 1;
   7.248    ret = (*symtab->hash_table->get)(symtab->hash_table, &key, &value, 0);
   7.249    if (ret == 0) {
   7.250 -    struct elf_symbol *sym = value.data;
   7.251 +    symtab_symbol *sym = value.data;
   7.252      uintptr_t rslt = (uintptr_t) ((char*)base + sym->offset);
   7.253      if (sym_size) *sym_size = sym->size;
   7.254      return rslt;
   7.255 @@ -238,7 +387,7 @@
   7.256    int n = 0;
   7.257    if (!symtab) return NULL;
   7.258    for (; n < symtab->num_symbols; n++) {
   7.259 -    struct elf_symbol* sym = &(symtab->symbols[n]);
   7.260 +    symtab_symbol* sym = &(symtab->symbols[n]);
   7.261      if (sym->name != NULL &&
   7.262        offset >= sym->offset && offset < sym->offset + sym->size) {
   7.263        if (poffset) *poffset = (offset - sym->offset);
     8.1 --- a/agent/src/os/bsd/symtab.h	Fri Mar 15 11:44:33 2013 -0700
     8.2 +++ b/agent/src/os/bsd/symtab.h	Sun Mar 17 08:57:56 2013 -0700
     8.3 @@ -1,5 +1,5 @@
     8.4  /*
     8.5 - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
     8.6 + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
     8.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     8.8   *
     8.9   * This code is free software; you can redistribute it and/or modify it
    8.10 @@ -27,11 +27,11 @@
    8.11  
    8.12  #include <stdint.h>
    8.13  
    8.14 -// interface to manage ELF symbol tables
    8.15 +// interface to manage ELF or MachO symbol tables
    8.16  
    8.17  struct symtab;
    8.18  
    8.19 -// build symbol table for a given ELF file descriptor
    8.20 +// build symbol table for a given ELF or MachO file escriptor
    8.21  struct symtab* build_symtab(int fd);
    8.22  
    8.23  // destroy the symbol table
     9.1 --- a/agent/src/share/classes/sun/jvm/hotspot/BsdVtblAccess.java	Fri Mar 15 11:44:33 2013 -0700
     9.2 +++ b/agent/src/share/classes/sun/jvm/hotspot/BsdVtblAccess.java	Sun Mar 17 08:57:56 2013 -0700
     9.3 @@ -1,5 +1,5 @@
     9.4  /*
     9.5 - * Copyright (c) 2002, 2003, Oracle and/or its affiliates. All rights reserved.
     9.6 + * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
     9.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     9.8   *
     9.9   * This code is free software; you can redistribute it and/or modify it
    9.10 @@ -34,11 +34,18 @@
    9.11    public BsdVtblAccess(SymbolLookup symbolLookup,
    9.12                           String[] dllNames) {
    9.13      super(symbolLookup, dllNames);
    9.14 -
    9.15 -    if (symbolLookup.lookup("libjvm.so", "__vt_10JavaThread") != null ||
    9.16 -        symbolLookup.lookup("libjvm_g.so", "__vt_10JavaThread") != null) {
    9.17 +    boolean oldVT = false;
    9.18 +    boolean isDarwin = dllNames[0].lastIndexOf(".dylib") != -1;
    9.19 +    String vtJavaThread = isDarwin ? "_vt_10JavaThread" : "__vt_10JavaThread";
    9.20 +    for (String dllName : dllNames) {
    9.21 +       if (symbolLookup.lookup(dllName, vtJavaThread) != null) {
    9.22 +         oldVT = true;
    9.23 +         break;
    9.24 +       }
    9.25 +    }
    9.26 +    if (oldVT) {
    9.27         // old C++ ABI
    9.28 -       vt = "__vt_";
    9.29 +       vt = isDarwin ? "_vt_" :  "__vt_";
    9.30      } else {
    9.31         // new C++ ABI
    9.32         vt = "_ZTV";
    10.1 --- a/agent/src/share/classes/sun/jvm/hotspot/CommandProcessor.java	Fri Mar 15 11:44:33 2013 -0700
    10.2 +++ b/agent/src/share/classes/sun/jvm/hotspot/CommandProcessor.java	Sun Mar 17 08:57:56 2013 -0700
    10.3 @@ -1517,7 +1517,7 @@
    10.4                          ByteArrayOutputStream bos = new ByteArrayOutputStream();
    10.5                          thread.printThreadIDOn(new PrintStream(bos));
    10.6                          if (all || bos.toString().equals(name)) {
    10.7 -                            out.println(bos.toString() + " = " + thread.getAddress());
    10.8 +                            out.println("Thread " + bos.toString() + " Address: " + thread.getAddress());
    10.9                              HTMLGenerator gen = new HTMLGenerator(false);
   10.10                              try {
   10.11                                  out.println(gen.genHTMLForJavaStackTrace(thread));
   10.12 @@ -1546,7 +1546,7 @@
   10.13                          ByteArrayOutputStream bos = new ByteArrayOutputStream();
   10.14                          thread.printThreadIDOn(new PrintStream(bos));
   10.15                          if (all || bos.toString().equals(name)) {
   10.16 -                            out.println(bos.toString() + " = " + thread.getAddress());
   10.17 +                            out.println("Thread " + bos.toString() + " Address " + thread.getAddress());
   10.18                              if (!all) return;
   10.19                          }
   10.20                      }
    11.1 --- a/agent/src/share/classes/sun/jvm/hotspot/HotSpotAgent.java	Fri Mar 15 11:44:33 2013 -0700
    11.2 +++ b/agent/src/share/classes/sun/jvm/hotspot/HotSpotAgent.java	Sun Mar 17 08:57:56 2013 -0700
    11.3 @@ -1,5 +1,5 @@
    11.4  /*
    11.5 - * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
    11.6 + * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
    11.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    11.8   *
    11.9   * This code is free software; you can redistribute it and/or modify it
   11.10 @@ -311,6 +311,8 @@
   11.11                  setupDebuggerLinux();
   11.12              } else if (os.equals("bsd")) {
   11.13                  setupDebuggerBsd();
   11.14 +            } else if (os.equals("darwin")) {
   11.15 +                setupDebuggerDarwin();
   11.16              } else {
   11.17                  // Add support for more operating systems here
   11.18                  throw new DebuggerException("Operating system " + os + " not yet supported");
   11.19 @@ -370,6 +372,10 @@
   11.20                  db = new HotSpotTypeDataBase(machDesc,
   11.21                  new BsdVtblAccess(debugger, jvmLibNames),
   11.22                  debugger, jvmLibNames);
   11.23 +            } else if (os.equals("darwin")) {
   11.24 +                db = new HotSpotTypeDataBase(machDesc,
   11.25 +                new BsdVtblAccess(debugger, jvmLibNames),
   11.26 +                debugger, jvmLibNames);
   11.27              } else {
   11.28                  throw new DebuggerException("OS \"" + os + "\" not yet supported (no VtblAccess yet)");
   11.29              }
   11.30 @@ -459,6 +465,8 @@
   11.31              setupJVMLibNamesLinux();
   11.32          } else if (os.equals("bsd")) {
   11.33              setupJVMLibNamesBsd();
   11.34 +        } else if (os.equals("darwin")) {
   11.35 +            setupJVMLibNamesDarwin();
   11.36          } else {
   11.37              throw new RuntimeException("Unknown OS type");
   11.38          }
   11.39 @@ -567,6 +575,29 @@
   11.40          jvmLibNames = new String[] { "libjvm.so", "libjvm_g.so" };
   11.41      }
   11.42  
   11.43 +    //
   11.44 +    // Darwin
   11.45 +    //
   11.46 +
   11.47 +    private void setupDebuggerDarwin() {
   11.48 +        setupJVMLibNamesDarwin();
   11.49 +
   11.50 +        if (cpu.equals("amd64") || cpu.equals("x86_64")) {
   11.51 +            machDesc = new MachineDescriptionAMD64();
   11.52 +        } else {
   11.53 +            throw new DebuggerException("Darwin only supported on x86_64. Current arch: " + cpu);
   11.54 +        }
   11.55 +
   11.56 +        BsdDebuggerLocal dbg = new BsdDebuggerLocal(machDesc, !isServer);
   11.57 +        debugger = dbg;
   11.58 +
   11.59 +        attachDebugger();
   11.60 +    }
   11.61 +
   11.62 +    private void setupJVMLibNamesDarwin() {
   11.63 +        jvmLibNames = new String[] { "libjvm.dylib", "libjvm_g.dylib" };
   11.64 +    }
   11.65 +
   11.66      /** Convenience routine which should be called by per-platform
   11.67        debugger setup. Should not be called when startupMode is
   11.68        REMOTE_MODE. */
    12.1 --- a/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdDebuggerLocal.java	Fri Mar 15 11:44:33 2013 -0700
    12.2 +++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdDebuggerLocal.java	Sun Mar 17 08:57:56 2013 -0700
    12.3 @@ -1,5 +1,5 @@
    12.4  /*
    12.5 - * Copyright (c) 2002, 2008, Oracle and/or its affiliates. All rights reserved.
    12.6 + * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
    12.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    12.8   *
    12.9   * This code is free software; you can redistribute it and/or modify it
   12.10 @@ -31,6 +31,9 @@
   12.11  import sun.jvm.hotspot.debugger.x86.*;
   12.12  import sun.jvm.hotspot.debugger.cdbg.*;
   12.13  import sun.jvm.hotspot.utilities.*;
   12.14 +import sun.jvm.hotspot.runtime.VM;
   12.15 +import sun.jvm.hotspot.runtime.Threads;
   12.16 +import sun.jvm.hotspot.runtime.JavaThread;
   12.17  import java.lang.reflect.*;
   12.18  
   12.19  /** <P> An implementation of the JVMDebugger interface. The basic debug
   12.20 @@ -51,10 +54,11 @@
   12.21  public class BsdDebuggerLocal extends DebuggerBase implements BsdDebugger {
   12.22      private boolean useGCC32ABI;
   12.23      private boolean attached;
   12.24 -    private long    p_ps_prochandle; // native debugger handle
   12.25 -    private long    symbolicator; // macosx symbolicator handle
   12.26 -    private long    task; // macosx task handle
   12.27 +    private long    p_ps_prochandle;      // native debugger handle
   12.28 +    private long    symbolicator;         // macosx symbolicator handle
   12.29 +    private long    task;                 // macosx task handle
   12.30      private boolean isCore;
   12.31 +    private boolean isDarwin;             // variant for bsd
   12.32  
   12.33      // CDebugger support
   12.34      private BsdCDebugger cdbg;
   12.35 @@ -208,6 +212,7 @@
   12.36              }
   12.37          }
   12.38  
   12.39 +        isDarwin = getOS().equals("darwin");
   12.40          workerThread = new BsdDebuggerLocalWorkerThread(this);
   12.41          workerThread.start();
   12.42      }
   12.43 @@ -240,8 +245,11 @@
   12.44  
   12.45      /* called from attach methods */
   12.46      private void findABIVersion() throws DebuggerException {
   12.47 -        if (lookupByName0("libjvm.so", "__vt_10JavaThread") != 0 ||
   12.48 -            lookupByName0("libjvm_g.so", "__vt_10JavaThread") != 0) {
   12.49 +        String libjvmName = isDarwin ? "libjvm.dylib" : "libjvm.so";
   12.50 +        String libjvm_gName = isDarwin? "libjvm_g.dylib" : "libjvm_g.so";
   12.51 +        String javaThreadVt = isDarwin ? "_vt_10JavaThread" : "__vt_10JavaThread";
   12.52 +        if (lookupByName0(libjvmName, javaThreadVt) != 0 ||
   12.53 +            lookupByName0(libjvm_gName, javaThreadVt) != 0) {
   12.54              // old C++ ABI
   12.55              useGCC32ABI = false;
   12.56          } else {
   12.57 @@ -360,7 +368,8 @@
   12.58          }
   12.59  
   12.60          if (isCore) {
   12.61 -            long addr = lookupByName0(objectName, symbol);
   12.62 +            // MacOSX symbol with "_" as leading
   12.63 +            long addr = lookupByName0(objectName, isDarwin ? "_" + symbol : symbol);
   12.64              return (addr == 0)? null : new BsdAddress(this, handleGCC32ABI(addr, symbol));
   12.65          } else {
   12.66              class LookupByNameTask implements WorkerThreadTask {
   12.67 @@ -403,12 +412,12 @@
   12.68      public ThreadProxy getThreadForIdentifierAddress(Address threadIdAddr, Address uniqueThreadIdAddr) {
   12.69          return new BsdThread(this, threadIdAddr, uniqueThreadIdAddr);
   12.70      }
   12.71 +
   12.72      @Override
   12.73      public ThreadProxy getThreadForIdentifierAddress(Address addr) {
   12.74          throw new RuntimeException("unimplemented");
   12.75      }
   12.76  
   12.77 -
   12.78      /** From the ThreadAccess interface via Debugger and JVMDebugger */
   12.79      public ThreadProxy getThreadForThreadId(long id) {
   12.80          return new BsdThread(this, id);
   12.81 @@ -601,6 +610,33 @@
   12.82          throw new DebuggerException("Unimplemented");
   12.83      }
   12.84  
   12.85 +    /** this functions used for core file reading and called from native attach0,
   12.86 +        it returns an array of long integers as
   12.87 +        [thread_id, stack_start, stack_end, thread_id, stack_start, stack_end, ....] for
   12.88 +        all java threads recorded in Threads. Also adds the ThreadProxy to threadList */
   12.89 +    public long[] getJavaThreadsInfo() {
   12.90 +        requireAttach();
   12.91 +        Threads threads = VM.getVM().getThreads();
   12.92 +        int len = threads.getNumberOfThreads();
   12.93 +        long[] result = new long[len * 3];    // triple
   12.94 +        JavaThread t = threads.first();
   12.95 +        long beg, end;
   12.96 +        int i = 0;
   12.97 +        while (t != null) {
   12.98 +            end = t.getStackBaseValue();
   12.99 +            beg = end - t.getStackSize();
  12.100 +            BsdThread bsdt = (BsdThread)t.getThreadProxy();
  12.101 +            long uid = bsdt.getUniqueThreadId();
  12.102 +            if (threadList != null) threadList.add(bsdt);
  12.103 +            result[i] = uid;
  12.104 +            result[i + 1] = beg;
  12.105 +            result[i + 2] = end;
  12.106 +            t = t.next();
  12.107 +            i += 3;
  12.108 +        }
  12.109 +        return result;
  12.110 +    }
  12.111 +
  12.112      static {
  12.113          System.loadLibrary("saproc");
  12.114          init0();
    13.1 --- a/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdThread.java	Fri Mar 15 11:44:33 2013 -0700
    13.2 +++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdThread.java	Sun Mar 17 08:57:56 2013 -0700
    13.3 @@ -1,5 +1,5 @@
    13.4  /*
    13.5 - * Copyright (c) 2002, 2003, Oracle and/or its affiliates. All rights reserved.
    13.6 + * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
    13.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    13.8   *
    13.9   * This code is free software; you can redistribute it and/or modify it
   13.10 @@ -44,7 +44,8 @@
   13.11  
   13.12      BsdThread(BsdDebugger debugger, long id) {
   13.13          this.debugger = debugger;
   13.14 -        this.thread_id = (int) id;
   13.15 +        // use unique_thread_id to identify thread
   13.16 +        this.unique_thread_id = id;
   13.17      }
   13.18  
   13.19      public boolean equals(Object obj) {
   13.20 @@ -52,7 +53,7 @@
   13.21              return false;
   13.22          }
   13.23  
   13.24 -        return (((BsdThread) obj).thread_id == thread_id);
   13.25 +        return (((BsdThread) obj).unique_thread_id == unique_thread_id);
   13.26      }
   13.27  
   13.28      public int hashCode() {
   13.29 @@ -80,4 +81,9 @@
   13.30        throws IllegalThreadStateException, DebuggerException {
   13.31          throw new DebuggerException("Unimplemented");
   13.32      }
   13.33 +
   13.34 +    /** this is not interface function, used in core file to get unique thread id on Macosx*/
   13.35 +    public long getUniqueThreadId() {
   13.36 +        return unique_thread_id;
   13.37 +    }
   13.38  }
    14.1 --- a/agent/src/share/classes/sun/jvm/hotspot/runtime/JavaThread.java	Fri Mar 15 11:44:33 2013 -0700
    14.2 +++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/JavaThread.java	Sun Mar 17 08:57:56 2013 -0700
    14.3 @@ -1,5 +1,5 @@
    14.4  /*
    14.5 - * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
    14.6 + * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
    14.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    14.8   *
    14.9   * This code is free software; you can redistribute it and/or modify it
   14.10 @@ -320,6 +320,10 @@
   14.11      return stackBaseField.getValue(addr);
   14.12    }
   14.13  
   14.14 +  public long getStackBaseValue() {
   14.15 +    return VM.getVM().getAddressValue(getStackBase());
   14.16 +  }
   14.17 +
   14.18    public long getStackSize() {
   14.19      return stackSizeField.getValue(addr);
   14.20    }
    15.1 --- a/agent/src/share/classes/sun/jvm/hotspot/runtime/Threads.java	Fri Mar 15 11:44:33 2013 -0700
    15.2 +++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/Threads.java	Sun Mar 17 08:57:56 2013 -0700
    15.3 @@ -1,5 +1,5 @@
    15.4  /*
    15.5 - * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
    15.6 + * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
    15.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    15.8   *
    15.9   * This code is free software; you can redistribute it and/or modify it
   15.10 @@ -42,6 +42,7 @@
   15.11  public class Threads {
   15.12      private static JavaThreadFactory threadFactory;
   15.13      private static AddressField      threadListField;
   15.14 +    private static CIntegerField     numOfThreadsField;
   15.15      private static VirtualConstructor virtualConstructor;
   15.16      private static JavaThreadPDAccess access;
   15.17  
   15.18 @@ -57,6 +58,7 @@
   15.19          Type type = db.lookupType("Threads");
   15.20  
   15.21          threadListField = type.getAddressField("_thread_list");
   15.22 +        numOfThreadsField = type.getCIntegerField("_number_of_threads");
   15.23  
   15.24          // Instantiate appropriate platform-specific JavaThreadFactory
   15.25          String os  = VM.getVM().getOS();
   15.26 @@ -102,6 +104,10 @@
   15.27              } else if (cpu.equals("amd64") || cpu.equals("x86_64")) {
   15.28                  access = new BsdAMD64JavaThreadPDAccess();
   15.29              }
   15.30 +        } else if (os.equals("darwin")) {
   15.31 +            if (cpu.equals("amd64") || cpu.equals("x86_64")) {
   15.32 +                access = new BsdAMD64JavaThreadPDAccess();
   15.33 +            }
   15.34          }
   15.35  
   15.36          if (access == null) {
   15.37 @@ -144,6 +150,10 @@
   15.38          return createJavaThreadWrapper(threadAddr);
   15.39      }
   15.40  
   15.41 +    public int getNumberOfThreads() {
   15.42 +        return (int) numOfThreadsField.getValue();
   15.43 +    }
   15.44 +
   15.45      /** Routine for instantiating appropriately-typed wrapper for a
   15.46        JavaThread. Currently needs to be public for OopUtilities to
   15.47        access it. */
    16.1 --- a/agent/src/share/classes/sun/jvm/hotspot/tools/PStack.java	Fri Mar 15 11:44:33 2013 -0700
    16.2 +++ b/agent/src/share/classes/sun/jvm/hotspot/tools/PStack.java	Sun Mar 17 08:57:56 2013 -0700
    16.3 @@ -1,5 +1,5 @@
    16.4  /*
    16.5 - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
    16.6 + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
    16.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    16.8   *
    16.9   * This code is free software; you can redistribute it and/or modify it
   16.10 @@ -32,6 +32,7 @@
   16.11  import sun.jvm.hotspot.debugger.cdbg.*;
   16.12  import sun.jvm.hotspot.oops.*;
   16.13  import sun.jvm.hotspot.runtime.*;
   16.14 +import sun.jvm.hotspot.utilities.PlatformInfo;
   16.15  
   16.16  public class PStack extends Tool {
   16.17      // in non-verbose mode, Method*s are not printed in java frames
   16.18 @@ -54,6 +55,11 @@
   16.19     }
   16.20  
   16.21     public void run(PrintStream out, Debugger dbg) {
   16.22 +      if (PlatformInfo.getOS().equals("darwin")) {
   16.23 +        out.println("Not available on Darwin");
   16.24 +        return;
   16.25 +      }
   16.26 +
   16.27        CDebugger cdbg = dbg.getCDebugger();
   16.28        if (cdbg != null) {
   16.29           ConcurrentLocksPrinter concLocksPrinter = null;
    17.1 --- a/agent/src/share/classes/sun/jvm/hotspot/utilities/PlatformInfo.java	Fri Mar 15 11:44:33 2013 -0700
    17.2 +++ b/agent/src/share/classes/sun/jvm/hotspot/utilities/PlatformInfo.java	Sun Mar 17 08:57:56 2013 -0700
    17.3 @@ -1,5 +1,5 @@
    17.4  /*
    17.5 - * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
    17.6 + * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
    17.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    17.8   *
    17.9   * This code is free software; you can redistribute it and/or modify it
   17.10 @@ -43,8 +43,8 @@
   17.11        return "bsd";
   17.12      } else if (os.equals("OpenBSD")) {
   17.13        return "bsd";
   17.14 -    } else if (os.equals("Darwin") || os.contains("OS X")) {
   17.15 -      return "bsd";
   17.16 +    } else if (os.contains("Darwin") || os.contains("OS X")) {
   17.17 +      return "darwin";
   17.18      } else if (os.startsWith("Windows")) {
   17.19        return "win32";
   17.20      } else {
    18.1 --- a/agent/src/share/native/sadis.c	Fri Mar 15 11:44:33 2013 -0700
    18.2 +++ b/agent/src/share/native/sadis.c	Sun Mar 17 08:57:56 2013 -0700
    18.3 @@ -1,5 +1,5 @@
    18.4  /*
    18.5 - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
    18.6 + * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
    18.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    18.8   *
    18.9   * This code is free software; you can redistribute it and/or modify it
   18.10 @@ -48,7 +48,10 @@
   18.11  
   18.12  #include <string.h>
   18.13  #include <dlfcn.h>
   18.14 +
   18.15 +#ifndef __APPLE__
   18.16  #include <link.h>
   18.17 +#endif
   18.18  
   18.19  #endif
   18.20  
   18.21 @@ -109,9 +112,7 @@
   18.22                                                                             jstring libname_s) {
   18.23    uintptr_t func = 0;
   18.24    const char* error_message = NULL;
   18.25 -  const char* java_home;
   18.26    jboolean isCopy;
   18.27 -  uintptr_t *handle = NULL;
   18.28  
   18.29    const char * jrepath = (*env)->GetStringUTFChars(env, jrepath_s, &isCopy); // like $JAVA_HOME/jre/lib/sparc/
   18.30    const char * libname = (*env)->GetStringUTFChars(env, libname_s, &isCopy);
   18.31 @@ -167,7 +168,8 @@
   18.32                               void* event_stream,
   18.33                               int (*printf_callback)(void*, const char*, ...),
   18.34                               void* printf_stream,
   18.35 -                             const char* options);
   18.36 +                             const char* options,
   18.37 +                             int newline);
   18.38  
   18.39  /* container for call back state when decoding instructions */
   18.40  typedef struct {
   18.41 @@ -281,7 +283,7 @@
   18.42                                                           end - start,
   18.43                                                           &event_to_env,  (void*) &denv,
   18.44                                                           &printf_to_env, (void*) &denv,
   18.45 -                                                         options);
   18.46 +                                                         options, 0 /* newline */);
   18.47  
   18.48    /* cleanup */
   18.49    (*env)->ReleaseByteArrayElements(env, code, start, JNI_ABORT);
    19.1 --- a/make/bsd/makefiles/saproc.make	Fri Mar 15 11:44:33 2013 -0700
    19.2 +++ b/make/bsd/makefiles/saproc.make	Sun Mar 17 08:57:56 2013 -0700
    19.3 @@ -1,5 +1,5 @@
    19.4  #
    19.5 -# Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
    19.6 +# Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
    19.7  # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    19.8  #
    19.9  # This code is free software; you can redistribute it and/or modify it
   19.10 @@ -24,7 +24,7 @@
   19.11  
   19.12  # Rules to build serviceability agent library, used by vm.make
   19.13  
   19.14 -# libsaproc.so: serviceability agent
   19.15 +# libsaproc.so(dylib): serviceability agent
   19.16  SAPROC   = saproc
   19.17  
   19.18  ifeq ($(OS_VENDOR), Darwin)
   19.19 @@ -37,7 +37,7 @@
   19.20  
   19.21  SASRCDIR = $(AGENT_DIR)/src/os/$(Platform_os_family)
   19.22  
   19.23 -NON_STUB_SASRCFILES = $(SASRCDIR)/salibelf.c                 \
   19.24 +BSD_NON_STUB_SASRCFILES = $(SASRCDIR)/salibelf.c             \
   19.25                        $(SASRCDIR)/symtab.c                   \
   19.26                        $(SASRCDIR)/libproc_impl.c             \
   19.27                        $(SASRCDIR)/ps_proc.c                  \
   19.28 @@ -45,13 +45,19 @@
   19.29                        $(SASRCDIR)/BsdDebuggerLocal.c         \
   19.30                        $(AGENT_DIR)/src/share/native/sadis.c
   19.31  
   19.32 +DARWIN_NON_STUB_SASRCFILES = $(SASRCDIR)/symtab.c            \
   19.33 +                      $(SASRCDIR)/libproc_impl.c             \
   19.34 +                      $(SASRCDIR)/ps_core.c                  \
   19.35 +                      $(SASRCDIR)/MacosxDebuggerLocal.m      \
   19.36 +                      $(AGENT_DIR)/src/share/native/sadis.c
   19.37 +
   19.38  ifeq ($(OS_VENDOR), FreeBSD)
   19.39 -  SASRCFILES = $(NON_STUB_SASRCFILES)
   19.40 +  SASRCFILES = $(BSD_NON_STUB_SASRCFILES)
   19.41    SALIBS = -lutil -lthread_db
   19.42    SAARCH = $(ARCHFLAG)
   19.43  else
   19.44    ifeq ($(OS_VENDOR), Darwin)
   19.45 -    SASRCFILES = $(SASRCDIR)/MacosxDebuggerLocal.m
   19.46 +    SASRCFILES = $(DARWIN_NON_STUB_SASRCFILES)
   19.47      SALIBS = -g -framework Foundation -F/System/Library/Frameworks/JavaVM.framework/Frameworks -framework JavaNativeFoundation -framework Security -framework CoreFoundation
   19.48      #objc compiler blows up on -march=i586, perhaps it should not be included in the macosx intel 32-bit C++ compiles?
   19.49      SAARCH = $(subst -march=i586,,$(ARCHFLAG))
   19.50 @@ -102,7 +108,7 @@
   19.51  	fi
   19.52  	@echo Making SA debugger back-end...
   19.53  	$(QUIETLY) $(CC) -D$(BUILDARCH) -D_GNU_SOURCE                   \
   19.54 -                   $(SYMFLAG) $(SAARCH) $(SHARED_FLAG) $(PICFLAG)     \
   19.55 +	           $(SYMFLAG) $(SAARCH) $(SHARED_FLAG) $(PICFLAG)       \
   19.56  	           -I$(SASRCDIR)                                        \
   19.57  	           -I$(GENERATED)                                       \
   19.58  	           $(BOOT_JAVA_INCLUDES)                                \
    20.1 --- a/src/share/vm/classfile/classLoaderData.cpp	Fri Mar 15 11:44:33 2013 -0700
    20.2 +++ b/src/share/vm/classfile/classLoaderData.cpp	Sun Mar 17 08:57:56 2013 -0700
    20.3 @@ -105,6 +105,7 @@
    20.4  void ClassLoaderData::classes_do(KlassClosure* klass_closure) {
    20.5    for (Klass* k = _klasses; k != NULL; k = k->next_link()) {
    20.6      klass_closure->do_klass(k);
    20.7 +    assert(k != k->next_link(), "no loops!");
    20.8    }
    20.9  }
   20.10  
   20.11 @@ -113,6 +114,7 @@
   20.12      if (k->oop_is_instance()) {
   20.13        f(InstanceKlass::cast(k));
   20.14      }
   20.15 +    assert(k != k->next_link(), "no loops!");
   20.16    }
   20.17  }
   20.18  
   20.19 @@ -258,6 +260,7 @@
   20.20        return;
   20.21      }
   20.22      prev = k;
   20.23 +    assert(k != k->next_link(), "no loops!");
   20.24    }
   20.25    ShouldNotReachHere();   // should have found this class!!
   20.26  }
   20.27 @@ -439,6 +442,7 @@
   20.28      while (k != NULL) {
   20.29        out->print_cr("klass "PTR_FORMAT", %s, CT: %d, MUT: %d", k, k->name()->as_C_string(),
   20.30            k->has_modified_oops(), k->has_accumulated_modified_oops());
   20.31 +      assert(k != k->next_link(), "no loops!");
   20.32        k = k->next_link();
   20.33      }
   20.34    }
   20.35 @@ -465,6 +469,7 @@
   20.36    for (Klass* k = _klasses; k != NULL; k = k->next_link()) {
   20.37      guarantee(k->class_loader_data() == this, "Must be the same");
   20.38      k->verify();
   20.39 +    assert(k != k->next_link(), "no loops!");
   20.40    }
   20.41  }
   20.42  
    21.1 --- a/src/share/vm/classfile/systemDictionary.cpp	Fri Mar 15 11:44:33 2013 -0700
    21.2 +++ b/src/share/vm/classfile/systemDictionary.cpp	Sun Mar 17 08:57:56 2013 -0700
    21.3 @@ -804,6 +804,32 @@
    21.4        }
    21.5      } // load_instance_class loop
    21.6  
    21.7 +    if (HAS_PENDING_EXCEPTION) {
    21.8 +      // An exception, such as OOM could have happened at various places inside
    21.9 +      // load_instance_class. We might have partially initialized a shared class
   21.10 +      // and need to clean it up.
   21.11 +      if (class_loader.is_null()) {
   21.12 +        // In some cases k may be null. Let's find the shared class again.
   21.13 +        instanceKlassHandle ik(THREAD, find_shared_class(name));
   21.14 +        if (ik.not_null()) {
   21.15 +          if (ik->class_loader_data() == NULL) {
   21.16 +            // We didn't go as far as Klass::restore_unshareable_info(),
   21.17 +            // so nothing to clean up.
   21.18 +          } else {
   21.19 +            MutexLocker mu(SystemDictionary_lock, THREAD);
   21.20 +            Klass* kk = find_class(name, ik->class_loader_data());
   21.21 +            if (kk != NULL) {
   21.22 +              // No clean up is needed if the shared class has been entered
   21.23 +              // into system dictionary, as load_shared_class() won't be called
   21.24 +              // again.
   21.25 +            } else {
   21.26 +              clean_up_shared_class(ik, class_loader, THREAD);
   21.27 +            }
   21.28 +          }
   21.29 +        }
   21.30 +      }
   21.31 +    }
   21.32 +
   21.33      if (load_instance_added == true) {
   21.34        // clean up placeholder entries for LOAD_INSTANCE success or error
   21.35        // This brackets the SystemDictionary updates for both defining
   21.36 @@ -1140,11 +1166,6 @@
   21.37    return load_shared_class(ik, class_loader, THREAD);
   21.38  }
   21.39  
   21.40 -// Note well!  Changes to this method may affect oop access order
   21.41 -// in the shared archive.  Please take care to not make changes that
   21.42 -// adversely affect cold start time by changing the oop access order
   21.43 -// that is specified in dump.cpp MarkAndMoveOrderedReadOnly and
   21.44 -// MarkAndMoveOrderedReadWrite closures.
   21.45  instanceKlassHandle SystemDictionary::load_shared_class(
   21.46                   instanceKlassHandle ik, Handle class_loader, TRAPS) {
   21.47    assert(class_loader.is_null(), "non-null classloader for shared class?");
   21.48 @@ -1205,6 +1226,19 @@
   21.49    return ik;
   21.50  }
   21.51  
   21.52 +void SystemDictionary::clean_up_shared_class(instanceKlassHandle ik, Handle class_loader, TRAPS) {
   21.53 +  // Updating methods must be done under a lock so multiple
   21.54 +  // threads don't update these in parallel
   21.55 +  // Shared classes are all currently loaded by the bootstrap
   21.56 +  // classloader, so this will never cause a deadlock on
   21.57 +  // a custom class loader lock.
   21.58 +  {
   21.59 +    Handle lockObject = compute_loader_lock_object(class_loader, THREAD);
   21.60 +    check_loader_lock_contention(lockObject, THREAD);
   21.61 +    ObjectLocker ol(lockObject, THREAD, true);
   21.62 +    ik->remove_unshareable_info();
   21.63 +  }
   21.64 +}
   21.65  
   21.66  instanceKlassHandle SystemDictionary::load_instance_class(Symbol* class_name, Handle class_loader, TRAPS) {
   21.67    instanceKlassHandle nh = instanceKlassHandle(); // null Handle
    22.1 --- a/src/share/vm/classfile/systemDictionary.hpp	Fri Mar 15 11:44:33 2013 -0700
    22.2 +++ b/src/share/vm/classfile/systemDictionary.hpp	Sun Mar 17 08:57:56 2013 -0700
    22.3 @@ -621,6 +621,7 @@
    22.4                                                 Handle class_loader, TRAPS);
    22.5    static instanceKlassHandle load_shared_class(instanceKlassHandle ik,
    22.6                                                 Handle class_loader, TRAPS);
    22.7 +  static void clean_up_shared_class(instanceKlassHandle ik, Handle class_loader, TRAPS);
    22.8    static instanceKlassHandle load_instance_class(Symbol* class_name, Handle class_loader, TRAPS);
    22.9    static Handle compute_loader_lock_object(Handle class_loader, TRAPS);
   22.10    static void check_loader_lock_contention(Handle loader_lock, TRAPS);
    23.1 --- a/src/share/vm/memory/metaspace.cpp	Fri Mar 15 11:44:33 2013 -0700
    23.2 +++ b/src/share/vm/memory/metaspace.cpp	Sun Mar 17 08:57:56 2013 -0700
    23.3 @@ -334,6 +334,9 @@
    23.4  
    23.5    // byte_size is the size of the associated virtualspace.
    23.6  VirtualSpaceNode::VirtualSpaceNode(size_t byte_size) : _top(NULL), _next(NULL), _rs(0) {
    23.7 +  // align up to vm allocation granularity
    23.8 +  byte_size = align_size_up(byte_size, os::vm_allocation_granularity());
    23.9 +
   23.10    // This allocates memory with mmap.  For DumpSharedspaces, allocate the
   23.11    // space at low memory so that other shared images don't conflict.
   23.12    // This is the same address as memory needed for UseCompressedOops but
    24.1 --- a/src/share/vm/oops/klass.cpp	Fri Mar 15 11:44:33 2013 -0700
    24.2 +++ b/src/share/vm/oops/klass.cpp	Sun Mar 17 08:57:56 2013 -0700
    24.3 @@ -486,6 +486,12 @@
    24.4  }
    24.5  
    24.6  void Klass::remove_unshareable_info() {
    24.7 +  if (!DumpSharedSpaces) {
    24.8 +    // Clean up after OOM during class loading
    24.9 +    if (class_loader_data() != NULL) {
   24.10 +      class_loader_data()->remove_class(this);
   24.11 +    }
   24.12 +  }
   24.13    set_subklass(NULL);
   24.14    set_next_sibling(NULL);
   24.15    // Clear the java mirror
    25.1 --- a/src/share/vm/oops/method.cpp	Fri Mar 15 11:44:33 2013 -0700
    25.2 +++ b/src/share/vm/oops/method.cpp	Sun Mar 17 08:57:56 2013 -0700
    25.3 @@ -798,7 +798,15 @@
    25.4    backedge_counter()->reset();
    25.5    _adapter = NULL;
    25.6    _from_compiled_entry = NULL;
    25.7 -  assert(_method_data == NULL, "unexpected method data?");
    25.8 +
    25.9 +  // In case of DumpSharedSpaces, _method_data should always be NULL.
   25.10 +  //
   25.11 +  // During runtime (!DumpSharedSpaces), when we are cleaning a
   25.12 +  // shared class that failed to load, this->link_method() may
   25.13 +  // have already been called (before an exception happened), so
   25.14 +  // this->_method_data may not be NULL.
   25.15 +  assert(!DumpSharedSpaces || _method_data == NULL, "unexpected method data?");
   25.16 +
   25.17    set_method_data(NULL);
   25.18    set_interpreter_throwout_count(0);
   25.19    set_interpreter_invocation_count(0);

mercurial