0N/A/*
3991N/A * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
0N/A * published by the Free Software Foundation.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
1472N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
1472N/A * or visit www.oracle.com if you need additional information or have any
1472N/A * questions.
0N/A *
0N/A */
0N/A
0N/A#include <jni.h>
0N/A#include "libproc.h"
0N/A
0N/A#if defined(x86_64) && !defined(amd64)
0N/A#define amd64 1
0N/A#endif
0N/A
0N/A#ifdef i386
0N/A#include "sun_jvm_hotspot_debugger_x86_X86ThreadContext.h"
0N/A#endif
0N/A
0N/A#ifdef amd64
0N/A#include "sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext.h"
0N/A#endif
0N/A
0N/A#if defined(sparc) || defined(sparcv9)
0N/A#include "sun_jvm_hotspot_debugger_sparc_SPARCThreadContext.h"
0N/A#endif
0N/A
0N/Astatic jfieldID p_ps_prochandle_ID = 0;
0N/Astatic jfieldID threadList_ID = 0;
0N/Astatic jfieldID loadObjectList_ID = 0;
0N/A
0N/Astatic jmethodID createClosestSymbol_ID = 0;
0N/Astatic jmethodID createLoadObject_ID = 0;
0N/Astatic jmethodID getThreadForThreadId_ID = 0;
0N/Astatic jmethodID listAdd_ID = 0;
0N/A
0N/A#define CHECK_EXCEPTION_(value) if ((*env)->ExceptionOccurred(env)) { return value; }
0N/A#define CHECK_EXCEPTION if ((*env)->ExceptionOccurred(env)) { return;}
0N/A#define THROW_NEW_DEBUGGER_EXCEPTION_(str, value) { throw_new_debugger_exception(env, str); return value; }
0N/A#define THROW_NEW_DEBUGGER_EXCEPTION(str) { throw_new_debugger_exception(env, str); return;}
0N/A
3991N/Avoid throw_new_debugger_exception(JNIEnv* env, const char* errMsg) {
0N/A (*env)->ThrowNew(env, (*env)->FindClass(env, "sun/jvm/hotspot/debugger/DebuggerException"), errMsg);
0N/A}
0N/A
3991N/Astruct ps_prochandle* get_proc_handle(JNIEnv* env, jobject this_obj) {
0N/A jlong ptr = (*env)->GetLongField(env, this_obj, p_ps_prochandle_ID);
0N/A return (struct ps_prochandle*)(intptr_t)ptr;
0N/A}
0N/A
0N/A/*
0N/A * Class: sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal
0N/A * Method: init0
0N/A * Signature: ()V
0N/A */
0N/AJNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal_init0
0N/A (JNIEnv *env, jclass cls) {
0N/A jclass listClass;
0N/A
0N/A if (init_libproc(getenv("LIBSAPROC_DEBUG")) != true) {
0N/A THROW_NEW_DEBUGGER_EXCEPTION("can't initialize libproc");
0N/A }
0N/A
0N/A // fields we use
0N/A p_ps_prochandle_ID = (*env)->GetFieldID(env, cls, "p_ps_prochandle", "J");
0N/A CHECK_EXCEPTION;
0N/A threadList_ID = (*env)->GetFieldID(env, cls, "threadList", "Ljava/util/List;");
0N/A CHECK_EXCEPTION;
0N/A loadObjectList_ID = (*env)->GetFieldID(env, cls, "loadObjectList", "Ljava/util/List;");
0N/A CHECK_EXCEPTION;
0N/A
0N/A // methods we use
0N/A createClosestSymbol_ID = (*env)->GetMethodID(env, cls, "createClosestSymbol",
0N/A "(Ljava/lang/String;J)Lsun/jvm/hotspot/debugger/cdbg/ClosestSymbol;");
0N/A CHECK_EXCEPTION;
0N/A createLoadObject_ID = (*env)->GetMethodID(env, cls, "createLoadObject",
0N/A "(Ljava/lang/String;JJ)Lsun/jvm/hotspot/debugger/cdbg/LoadObject;");
0N/A CHECK_EXCEPTION;
0N/A getThreadForThreadId_ID = (*env)->GetMethodID(env, cls, "getThreadForThreadId",
0N/A "(J)Lsun/jvm/hotspot/debugger/ThreadProxy;");
0N/A CHECK_EXCEPTION;
0N/A // java.util.List method we call
0N/A listClass = (*env)->FindClass(env, "java/util/List");
0N/A CHECK_EXCEPTION;
0N/A listAdd_ID = (*env)->GetMethodID(env, listClass, "add", "(Ljava/lang/Object;)Z");
0N/A CHECK_EXCEPTION;
0N/A}
0N/A
0N/AJNIEXPORT jint JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal_getAddressSize
0N/A (JNIEnv *env, jclass cls)
0N/A{
0N/A#ifdef _LP64
0N/A return 8;
0N/A#else
0N/A return 4;
0N/A#endif
0N/A
0N/A}
0N/A
0N/A
0N/Astatic void fillThreadsAndLoadObjects(JNIEnv* env, jobject this_obj, struct ps_prochandle* ph) {
0N/A int n = 0, i = 0;
0N/A
0N/A // add threads
0N/A n = get_num_threads(ph);
0N/A for (i = 0; i < n; i++) {
0N/A jobject thread;
0N/A jobject threadList;
0N/A lwpid_t lwpid;
0N/A
0N/A lwpid = get_lwp_id(ph, i);
0N/A thread = (*env)->CallObjectMethod(env, this_obj, getThreadForThreadId_ID,
0N/A (jlong)lwpid);
0N/A CHECK_EXCEPTION;
0N/A threadList = (*env)->GetObjectField(env, this_obj, threadList_ID);
0N/A CHECK_EXCEPTION;
0N/A (*env)->CallBooleanMethod(env, threadList, listAdd_ID, thread);
0N/A CHECK_EXCEPTION;
0N/A }
0N/A
0N/A // add load objects
0N/A n = get_num_libs(ph);
0N/A for (i = 0; i < n; i++) {
0N/A uintptr_t base;
0N/A const char* name;
0N/A jobject loadObject;
0N/A jobject loadObjectList;
0N/A
0N/A base = get_lib_base(ph, i);
0N/A name = get_lib_name(ph, i);
0N/A loadObject = (*env)->CallObjectMethod(env, this_obj, createLoadObject_ID,
0N/A (*env)->NewStringUTF(env, name), (jlong)0, (jlong)base);
0N/A CHECK_EXCEPTION;
0N/A loadObjectList = (*env)->GetObjectField(env, this_obj, loadObjectList_ID);
0N/A CHECK_EXCEPTION;
0N/A (*env)->CallBooleanMethod(env, loadObjectList, listAdd_ID, loadObject);
0N/A CHECK_EXCEPTION;
0N/A }
0N/A}
0N/A
0N/A/*
0N/A * Class: sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal
0N/A * Method: attach0
0N/A * Signature: (I)V
0N/A */
0N/AJNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal_attach0__I
0N/A (JNIEnv *env, jobject this_obj, jint jpid) {
0N/A
0N/A struct ps_prochandle* ph;
0N/A if ( (ph = Pgrab(jpid)) == NULL) {
0N/A THROW_NEW_DEBUGGER_EXCEPTION("Can't attach to the process");
0N/A }
0N/A (*env)->SetLongField(env, this_obj, p_ps_prochandle_ID, (jlong)(intptr_t)ph);
0N/A fillThreadsAndLoadObjects(env, this_obj, ph);
0N/A}
0N/A
0N/A/*
0N/A * Class: sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal
0N/A * Method: attach0
0N/A * Signature: (Ljava/lang/String;Ljava/lang/String;)V
0N/A */
0N/AJNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal_attach0__Ljava_lang_String_2Ljava_lang_String_2
0N/A (JNIEnv *env, jobject this_obj, jstring execName, jstring coreName) {
0N/A const char *execName_cstr;
0N/A const char *coreName_cstr;
0N/A jboolean isCopy;
0N/A struct ps_prochandle* ph;
0N/A
0N/A execName_cstr = (*env)->GetStringUTFChars(env, execName, &isCopy);
0N/A CHECK_EXCEPTION;
0N/A coreName_cstr = (*env)->GetStringUTFChars(env, coreName, &isCopy);
0N/A CHECK_EXCEPTION;
0N/A
0N/A if ( (ph = Pgrab_core(execName_cstr, coreName_cstr)) == NULL) {
0N/A (*env)->ReleaseStringUTFChars(env, execName, execName_cstr);
0N/A (*env)->ReleaseStringUTFChars(env, coreName, coreName_cstr);
0N/A THROW_NEW_DEBUGGER_EXCEPTION("Can't attach to the core file");
0N/A }
0N/A (*env)->SetLongField(env, this_obj, p_ps_prochandle_ID, (jlong)(intptr_t)ph);
0N/A (*env)->ReleaseStringUTFChars(env, execName, execName_cstr);
0N/A (*env)->ReleaseStringUTFChars(env, coreName, coreName_cstr);
0N/A fillThreadsAndLoadObjects(env, this_obj, ph);
0N/A}
0N/A
0N/A/*
0N/A * Class: sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal
0N/A * Method: detach0
0N/A * Signature: ()V
0N/A */
0N/AJNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal_detach0
0N/A (JNIEnv *env, jobject this_obj) {
0N/A struct ps_prochandle* ph = get_proc_handle(env, this_obj);
0N/A if (ph != NULL) {
0N/A Prelease(ph);
0N/A }
0N/A}
0N/A
0N/A/*
0N/A * Class: sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal
0N/A * Method: lookupByName0
0N/A * Signature: (Ljava/lang/String;Ljava/lang/String;)J
0N/A */
0N/AJNIEXPORT jlong JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal_lookupByName0
0N/A (JNIEnv *env, jobject this_obj, jstring objectName, jstring symbolName) {
0N/A const char *objectName_cstr, *symbolName_cstr;
0N/A jlong addr;
0N/A jboolean isCopy;
0N/A struct ps_prochandle* ph = get_proc_handle(env, this_obj);
0N/A
0N/A objectName_cstr = NULL;
0N/A if (objectName != NULL) {
0N/A objectName_cstr = (*env)->GetStringUTFChars(env, objectName, &isCopy);
0N/A CHECK_EXCEPTION_(0);
0N/A }
0N/A symbolName_cstr = (*env)->GetStringUTFChars(env, symbolName, &isCopy);
0N/A CHECK_EXCEPTION_(0);
0N/A
0N/A addr = (jlong) lookup_symbol(ph, objectName_cstr, symbolName_cstr);
0N/A
0N/A if (objectName_cstr != NULL) {
0N/A (*env)->ReleaseStringUTFChars(env, objectName, objectName_cstr);
0N/A }
0N/A (*env)->ReleaseStringUTFChars(env, symbolName, symbolName_cstr);
0N/A return addr;
0N/A}
0N/A
0N/A/*
0N/A * Class: sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal
0N/A * Method: lookupByAddress0
0N/A * Signature: (J)Lsun/jvm/hotspot/debugger/cdbg/ClosestSymbol;
0N/A */
0N/AJNIEXPORT jobject JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal_lookupByAddress0
0N/A (JNIEnv *env, jobject this_obj, jlong addr) {
0N/A uintptr_t offset;
0N/A const char* sym = NULL;
0N/A
0N/A struct ps_prochandle* ph = get_proc_handle(env, this_obj);
0N/A sym = symbol_for_pc(ph, (uintptr_t) addr, &offset);
0N/A if (sym == NULL) return 0;
0N/A return (*env)->CallObjectMethod(env, this_obj, createClosestSymbol_ID,
0N/A (*env)->NewStringUTF(env, sym), (jlong)offset);
0N/A}
0N/A
0N/A/*
0N/A * Class: sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal
0N/A * Method: readBytesFromProcess0
0N/A * Signature: (JJ)Lsun/jvm/hotspot/debugger/ReadResult;
0N/A */
0N/AJNIEXPORT jbyteArray JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal_readBytesFromProcess0
0N/A (JNIEnv *env, jobject this_obj, jlong addr, jlong numBytes) {
0N/A
0N/A jboolean isCopy;
0N/A jbyteArray array;
0N/A jbyte *bufPtr;
0N/A ps_err_e err;
0N/A
0N/A array = (*env)->NewByteArray(env, numBytes);
0N/A CHECK_EXCEPTION_(0);
0N/A bufPtr = (*env)->GetByteArrayElements(env, array, &isCopy);
0N/A CHECK_EXCEPTION_(0);
0N/A
0N/A err = ps_pdread(get_proc_handle(env, this_obj), (psaddr_t) (uintptr_t)addr, bufPtr, numBytes);
0N/A (*env)->ReleaseByteArrayElements(env, array, bufPtr, 0);
0N/A return (err == PS_OK)? array : 0;
0N/A}
0N/A
3991N/A#if defined(i386) || defined(ia64) || defined(amd64) || defined(sparc) || defined(sparcv9)
0N/AJNIEXPORT jlongArray JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal_getThreadIntegerRegisterSet0
0N/A (JNIEnv *env, jobject this_obj, jint lwp_id) {
0N/A
0N/A struct user_regs_struct gregs;
0N/A jboolean isCopy;
0N/A jlongArray array;
0N/A jlong *regs;
0N/A int i;
0N/A
0N/A struct ps_prochandle* ph = get_proc_handle(env, this_obj);
0N/A if (get_lwp_regs(ph, lwp_id, &gregs) != true) {
0N/A THROW_NEW_DEBUGGER_EXCEPTION_("get_thread_regs failed for a lwp", 0);
0N/A }
0N/A
0N/A#undef NPRGREG
0N/A#ifdef i386
0N/A#define NPRGREG sun_jvm_hotspot_debugger_x86_X86ThreadContext_NPRGREG
0N/A#endif
0N/A#ifdef ia64
0N/A#define NPRGREG IA64_REG_COUNT
0N/A#endif
0N/A#ifdef amd64
0N/A#define NPRGREG sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_NPRGREG
0N/A#endif
0N/A#if defined(sparc) || defined(sparcv9)
0N/A#define NPRGREG sun_jvm_hotspot_debugger_sparc_SPARCThreadContext_NPRGREG
0N/A#endif
0N/A
0N/A array = (*env)->NewLongArray(env, NPRGREG);
0N/A CHECK_EXCEPTION_(0);
0N/A regs = (*env)->GetLongArrayElements(env, array, &isCopy);
0N/A
0N/A#undef REG_INDEX
0N/A
0N/A#ifdef i386
0N/A#define REG_INDEX(reg) sun_jvm_hotspot_debugger_x86_X86ThreadContext_##reg
0N/A
0N/A regs[REG_INDEX(GS)] = (uintptr_t) gregs.xgs;
0N/A regs[REG_INDEX(FS)] = (uintptr_t) gregs.xfs;
0N/A regs[REG_INDEX(ES)] = (uintptr_t) gregs.xes;
0N/A regs[REG_INDEX(DS)] = (uintptr_t) gregs.xds;
0N/A regs[REG_INDEX(EDI)] = (uintptr_t) gregs.edi;
0N/A regs[REG_INDEX(ESI)] = (uintptr_t) gregs.esi;
0N/A regs[REG_INDEX(FP)] = (uintptr_t) gregs.ebp;
0N/A regs[REG_INDEX(SP)] = (uintptr_t) gregs.esp;
0N/A regs[REG_INDEX(EBX)] = (uintptr_t) gregs.ebx;
0N/A regs[REG_INDEX(EDX)] = (uintptr_t) gregs.edx;
0N/A regs[REG_INDEX(ECX)] = (uintptr_t) gregs.ecx;
0N/A regs[REG_INDEX(EAX)] = (uintptr_t) gregs.eax;
0N/A regs[REG_INDEX(PC)] = (uintptr_t) gregs.eip;
0N/A regs[REG_INDEX(CS)] = (uintptr_t) gregs.xcs;
0N/A regs[REG_INDEX(SS)] = (uintptr_t) gregs.xss;
0N/A
0N/A#endif /* i386 */
0N/A
0N/A#if ia64
0N/A regs = (*env)->GetLongArrayElements(env, array, &isCopy);
0N/A for (i = 0; i < NPRGREG; i++ ) {
0N/A regs[i] = 0xDEADDEAD;
0N/A }
0N/A#endif /* ia64 */
0N/A
0N/A#ifdef amd64
0N/A#define REG_INDEX(reg) sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_##reg
0N/A
0N/A regs[REG_INDEX(R15)] = gregs.r15;
0N/A regs[REG_INDEX(R14)] = gregs.r14;
0N/A regs[REG_INDEX(R13)] = gregs.r13;
0N/A regs[REG_INDEX(R12)] = gregs.r12;
0N/A regs[REG_INDEX(RBP)] = gregs.rbp;
0N/A regs[REG_INDEX(RBX)] = gregs.rbx;
0N/A regs[REG_INDEX(R11)] = gregs.r11;
0N/A regs[REG_INDEX(R10)] = gregs.r10;
0N/A regs[REG_INDEX(R9)] = gregs.r9;
0N/A regs[REG_INDEX(R8)] = gregs.r8;
0N/A regs[REG_INDEX(RAX)] = gregs.rax;
0N/A regs[REG_INDEX(RCX)] = gregs.rcx;
0N/A regs[REG_INDEX(RDX)] = gregs.rdx;
0N/A regs[REG_INDEX(RSI)] = gregs.rsi;
0N/A regs[REG_INDEX(RDI)] = gregs.rdi;
0N/A regs[REG_INDEX(RIP)] = gregs.rip;
0N/A regs[REG_INDEX(CS)] = gregs.cs;
0N/A regs[REG_INDEX(RSP)] = gregs.rsp;
0N/A regs[REG_INDEX(SS)] = gregs.ss;
0N/A regs[REG_INDEX(FSBASE)] = gregs.fs_base;
0N/A regs[REG_INDEX(GSBASE)] = gregs.gs_base;
0N/A regs[REG_INDEX(DS)] = gregs.ds;
0N/A regs[REG_INDEX(ES)] = gregs.es;
0N/A regs[REG_INDEX(FS)] = gregs.fs;
0N/A regs[REG_INDEX(GS)] = gregs.gs;
0N/A
0N/A#endif /* amd64 */
0N/A
0N/A#if defined(sparc) || defined(sparcv9)
0N/A
0N/A#define REG_INDEX(reg) sun_jvm_hotspot_debugger_sparc_SPARCThreadContext_##reg
0N/A
0N/A#ifdef _LP64
0N/A regs[REG_INDEX(R_PSR)] = gregs.tstate;
0N/A regs[REG_INDEX(R_PC)] = gregs.tpc;
0N/A regs[REG_INDEX(R_nPC)] = gregs.tnpc;
0N/A regs[REG_INDEX(R_Y)] = gregs.y;
0N/A#else
0N/A regs[REG_INDEX(R_PSR)] = gregs.psr;
0N/A regs[REG_INDEX(R_PC)] = gregs.pc;
0N/A regs[REG_INDEX(R_nPC)] = gregs.npc;
0N/A regs[REG_INDEX(R_Y)] = gregs.y;
0N/A#endif
0N/A regs[REG_INDEX(R_G0)] = 0 ;
0N/A regs[REG_INDEX(R_G1)] = gregs.u_regs[0];
0N/A regs[REG_INDEX(R_G2)] = gregs.u_regs[1];
0N/A regs[REG_INDEX(R_G3)] = gregs.u_regs[2];
0N/A regs[REG_INDEX(R_G4)] = gregs.u_regs[3];
0N/A regs[REG_INDEX(R_G5)] = gregs.u_regs[4];
0N/A regs[REG_INDEX(R_G6)] = gregs.u_regs[5];
0N/A regs[REG_INDEX(R_G7)] = gregs.u_regs[6];
0N/A regs[REG_INDEX(R_O0)] = gregs.u_regs[7];
0N/A regs[REG_INDEX(R_O1)] = gregs.u_regs[8];
0N/A regs[REG_INDEX(R_O2)] = gregs.u_regs[ 9];
0N/A regs[REG_INDEX(R_O3)] = gregs.u_regs[10];
0N/A regs[REG_INDEX(R_O4)] = gregs.u_regs[11];
0N/A regs[REG_INDEX(R_O5)] = gregs.u_regs[12];
0N/A regs[REG_INDEX(R_O6)] = gregs.u_regs[13];
0N/A regs[REG_INDEX(R_O7)] = gregs.u_regs[14];
0N/A#endif /* sparc */
0N/A
0N/A
0N/A (*env)->ReleaseLongArrayElements(env, array, regs, JNI_COMMIT);
0N/A return array;
0N/A}
3991N/A#endif