/* * Class: sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal * Method: readBytesFromProcess0 * Signature: (JJ)Lsun/jvm/hotspot/debugger/ReadResult; */ JNIEXPORT jbyteArray JNICALL Java_sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal_readBytesFromProcess0 (JNIEnv *env, jobject this_obj, jlong address, jlong numBytes) { jbyteArray array = env->NewByteArray(numBytes); CHECK_EXCEPTION_(0); jboolean isCopy; jbyte* bufPtr = env->GetByteArrayElements(array, &isCopy); CHECK_EXCEPTION_(0); jlong ps_prochandle_ptr = env->GetLongField(this_obj, ps_prochandle_ptr_ID); ps_err_e ret = ps_pread((struct ps_prochandle*) ps_prochandle_ptr, (psaddr_t)address, bufPtr, (size_t)numBytes); if(ret != PS_OK) { // Part of workaround for 4705086. jint libjvm_fd = env->GetIntField(this_obj, libjvm_fd_ID); jlong libjvm_text_start = env->GetLongField(this_obj, libjvm_text_start_ID); jlong libjvm_text_size = env->GetLongField(this_obj, libjvm_text_size_ID); // get the file descriptor for libjvm.so jlong offset = address - libjvm_text_start; // do bounds check to verify that the given address is in // libjvm text if (offset >= libjvm_text_size || offset < 0) { env->ReleaseByteArrayElements(array, bufPtr, JNI_COMMIT); // the address given is not in libjvm[_g].so text return jbyteArray(0); } ssize_t bytes_read = pread(libjvm_fd, bufPtr, numBytes, (off_t)offset); if (bytes_read != (ssize_t) numBytes) { env->ReleaseByteArrayElements(array, bufPtr, JNI_COMMIT); return jbyteArray(0); } } env->ReleaseByteArrayElements(array, bufPtr, JNI_COMMIT); return array; }
/* * Class: sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal * Method: readBytesFromProcess0 * Signature: (JJ)[B * Description: read bytes from debuggee process/core */ JNIEXPORT jbyteArray JNICALL Java_sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal_readBytesFromProcess0 (JNIEnv *env, jobject this_obj, jlong address, jlong numBytes) { jbyteArray array = env->NewByteArray(numBytes); CHECK_EXCEPTION_(0); jboolean isCopy; jbyte* bufPtr = env->GetByteArrayElements(array, &isCopy); CHECK_EXCEPTION_(0); jlong p_ps_prochandle = env->GetLongField(this_obj, p_ps_prochandle_ID); ps_err_e ret = ps_pread((struct ps_prochandle*) p_ps_prochandle, (psaddr_t)address, bufPtr, (size_t)numBytes); if (ret != PS_OK) { // part of the class sharing workaround. try shared heap area int classes_jsa_fd = env->GetIntField(this_obj, classes_jsa_fd_ID); if (classes_jsa_fd != -1 && address != (jlong)0) { print_debug("read failed at 0x%lx, attempting shared heap area\n", (long) address); struct FileMapHeader* pheader = (struct FileMapHeader*) env->GetLongField(this_obj, p_file_map_header_ID); // walk through the shared mappings -- we just have 4 of them. // so, linear walking is okay. for (int m = 0; m < NUM_SHARED_MAPS; m++) { // We can skip the non-read-only maps. These are mapped as MAP_PRIVATE // and hence will be read by libproc. Besides, the file copy may be // stale because the process might have modified those pages. if (pheader->_space[m]._read_only) { jlong baseAddress = (jlong) (uintptr_t) pheader->_space[m]._base; size_t usedSize = pheader->_space[m]._used; if (address >= baseAddress && address < (baseAddress + usedSize)) { // the given address falls in this shared heap area print_debug("found shared map at 0x%lx\n", (long) baseAddress); // If more data is asked than actually mapped from file, we need to zero fill // till the end-of-page boundary. But, java array new does that for us. we just // need to read as much as data available. #define MIN2(x, y) (((x) < (y))? (x) : (y)) jlong diff = address - baseAddress; jlong bytesToRead = MIN2(numBytes, usedSize - diff); off_t offset = pheader->_space[m]._file_offset + off_t(diff); ssize_t bytesRead = pread(classes_jsa_fd, bufPtr, bytesToRead, offset); if (bytesRead != bytesToRead) { env->ReleaseByteArrayElements(array, bufPtr, JNI_ABORT); print_debug("shared map read failed\n"); return jbyteArray(0); } else { print_debug("shared map read succeeded\n"); env->ReleaseByteArrayElements(array, bufPtr, 0); return array; } } // is in current map } // is read only map } // for shared maps } // classes_jsa_fd != -1 env->ReleaseByteArrayElements(array, bufPtr, JNI_ABORT); return jbyteArray(0); } else { env->ReleaseByteArrayElements(array, bufPtr, 0); return array; } }