1 /* 2 * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. 3 * Copyright (c) 2019, NTT DATA. 4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5 * 6 * This code is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License version 2 only, as 8 * published by the Free Software Foundation. 9 * 10 * This code is distributed in the hope that it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 * version 2 for more details (a copy is included in the LICENSE file that 14 * accompanied this code). 15 * 16 * You should have received a copy of the GNU General Public License version 17 * 2 along with this work; if not, write to the Free Software Foundation, 18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 * 20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 * or visit www.oracle.com if you need additional information or have any 22 * questions. 23 * 24 */ 25 26 #include <jni.h> 27 28 #include "dwarf.hpp" 29 #include "libproc.h" 30 31 #define CHECK_EXCEPTION if (env->ExceptionOccurred()) { return; } 32 33 static jfieldID p_dwarf_context_ID = 0; 34 static jint sa_RAX = -1; 35 static jint sa_RDX = -1; 36 static jint sa_RCX = -1; 37 static jint sa_RBX = -1; 38 static jint sa_RSI = -1; 39 static jint sa_RDI = -1; 40 static jint sa_RBP = -1; 41 static jint sa_RSP = -1; 42 static jint sa_R8 = -1; 43 static jint sa_R9 = -1; 44 static jint sa_R10 = -1; 45 static jint sa_R11 = -1; 46 static jint sa_R12 = -1; 47 static jint sa_R13 = -1; 48 static jint sa_R14 = -1; 49 static jint sa_R15 = -1; 50 51 static jlong get_dwarf_context(JNIEnv *env, jobject obj) { 52 return env->GetLongField(obj, p_dwarf_context_ID); 53 } 54 55 #define SET_REG(env, reg, reg_cls) \ 56 jfieldID reg##_ID = env->GetStaticFieldID(reg_cls, #reg, "I"); \ 57 CHECK_EXCEPTION \ 58 sa_##reg = env->GetStaticIntField(reg_cls, reg##_ID); \ 59 CHECK_EXCEPTION 60 61 /* 62 * Class: sun_jvm_hotspot_debugger_linux_amd64_DwarfParser 63 * Method: init0 64 * Signature: ()V 65 */ 66 extern "C" 67 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_linux_amd64_DwarfParser_init0 68 (JNIEnv *env, jclass this_cls) { 69 jclass cls = env->FindClass("sun/jvm/hotspot/debugger/linux/amd64/DwarfParser"); 70 CHECK_EXCEPTION 71 p_dwarf_context_ID = env->GetFieldID(cls, "p_dwarf_context", "J"); 72 CHECK_EXCEPTION 73 74 jclass reg_cls = env->FindClass("sun/jvm/hotspot/debugger/amd64/AMD64ThreadContext"); 75 CHECK_EXCEPTION 76 SET_REG(env, RAX, reg_cls); 77 SET_REG(env, RDX, reg_cls); 78 SET_REG(env, RCX, reg_cls); 79 SET_REG(env, RBX, reg_cls); 80 SET_REG(env, RSI, reg_cls); 81 SET_REG(env, RDI, reg_cls); 82 SET_REG(env, RBP, reg_cls); 83 SET_REG(env, RSP, reg_cls); 84 SET_REG(env, R8, reg_cls); 85 SET_REG(env, R9, reg_cls); 86 SET_REG(env, R10, reg_cls); 87 SET_REG(env, R11, reg_cls); 88 SET_REG(env, R12, reg_cls); 89 SET_REG(env, R13, reg_cls); 90 SET_REG(env, R14, reg_cls); 91 SET_REG(env, R15, reg_cls); 92 } 93 94 /* 95 * Class: sun_jvm_hotspot_debugger_linux_amd64_DwarfParser 96 * Method: createDwarfContext 97 * Signature: (J)J 98 */ 99 extern "C" 100 JNIEXPORT jlong JNICALL Java_sun_jvm_hotspot_debugger_linux_amd64_DwarfParser_createDwarfContext 101 (JNIEnv *env, jclass this_cls, jlong lib) { 102 jlong result = 0L; 103 104 DwarfParser *parser = new DwarfParser(reinterpret_cast<lib_info *>(lib)); 105 if (!parser->can_parsable()) { 106 jclass ex_cls = env->FindClass("sun/jvm/hotspot/debugger/DebuggerException"); 107 env->ThrowNew(ex_cls, "DWARF not found"); 108 return 0L; 109 } 110 111 return reinterpret_cast<jlong>(parser); 112 } 113 114 /* 115 * Class: sun_jvm_hotspot_debugger_linux_amd64_DwarfParser 116 * Method: destroyDwarfContext 117 * Signature: (J)V 118 */ 119 extern "C" 120 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_linux_amd64_DwarfParser_destroyDwarfContext 121 (JNIEnv *env, jclass this_cls, jlong context) { 122 DwarfParser *parser = reinterpret_cast<DwarfParser *>(context); 123 delete parser; 124 } 125 126 /* 127 * Class: sun_jvm_hotspot_debugger_linux_amd64_DwarfParser 128 * Method: isIn0 129 * Signature: (J)Z 130 */ 131 extern "C" 132 JNIEXPORT jboolean JNICALL Java_sun_jvm_hotspot_debugger_linux_amd64_DwarfParser_isIn0 133 (JNIEnv *env, jobject this_obj, jlong pc) { 134 DwarfParser *parser = reinterpret_cast<DwarfParser *>(get_dwarf_context(env, this_obj)); 135 return static_cast<jboolean>(parser->is_in(pc)); 136 } 137 138 /* 139 * Class: sun_jvm_hotspot_debugger_linux_amd64_DwarfParser 140 * Method: processDwarf0 141 * Signature: (J)V 142 */ 143 extern "C" 144 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_linux_amd64_DwarfParser_processDwarf0 145 (JNIEnv *env, jobject this_obj, jlong pc) { 146 DwarfParser *parser = reinterpret_cast<DwarfParser *>(get_dwarf_context(env, this_obj)); 147 parser->process_dwarf(pc); 148 } 149 150 /* 151 * Class: sun_jvm_hotspot_debugger_linux_amd64_DwarfParser 152 * Method: getCFARegister 153 * Signature: ()I 154 */ 155 extern "C" 156 JNIEXPORT jint JNICALL Java_sun_jvm_hotspot_debugger_linux_amd64_DwarfParser_getCFARegister 157 (JNIEnv *env, jobject this_obj) { 158 DwarfParser *parser = reinterpret_cast<DwarfParser *>(get_dwarf_context(env, this_obj)); 159 switch (parser->get_cfa_register()) { 160 case RAX: return sa_RAX; 161 case RDX: return sa_RDX; 162 case RCX: return sa_RCX; 163 case RBX: return sa_RBX; 164 case RSI: return sa_RSI; 165 case RDI: return sa_RDI; 166 case RBP: return sa_RBP; 167 case RSP: return sa_RSP; 168 case R8: return sa_R8; 169 case R9: return sa_R9; 170 case R10: return sa_R10; 171 case R11: return sa_R11; 172 case R12: return sa_R12; 173 case R13: return sa_R13; 174 case R14: return sa_R14; 175 case R15: return sa_R15; 176 default: return -1; 177 } 178 } 179 180 /* 181 * Class: sun_jvm_hotspot_debugger_linux_amd64_DwarfParser 182 * Method: getCFAOffset 183 * Signature: ()I 184 */ 185 extern "C" 186 JNIEXPORT jint JNICALL Java_sun_jvm_hotspot_debugger_linux_amd64_DwarfParser_getCFAOffset 187 (JNIEnv *env, jobject this_obj) { 188 DwarfParser *parser = reinterpret_cast<DwarfParser *>(get_dwarf_context(env, this_obj)); 189 return parser->get_cfa_offset(); 190 } 191 192 /* 193 * Class: sun_jvm_hotspot_debugger_linux_amd64_DwarfParser 194 * Method: getReturnAddressOffsetFromCFA 195 * Signature: ()I 196 */ 197 extern "C" 198 JNIEXPORT jint JNICALL Java_sun_jvm_hotspot_debugger_linux_amd64_DwarfParser_getReturnAddressOffsetFromCFA 199 (JNIEnv *env, jobject this_obj) { 200 DwarfParser *parser = reinterpret_cast<DwarfParser *>(get_dwarf_context(env, this_obj)); 201 return parser->get_ra_cfa_offset(); 202 } 203 204 /* 205 * Class: sun_jvm_hotspot_debugger_linux_amd64_DwarfParser 206 * Method: getBasePointerOffsetFromCFA 207 * Signature: ()I 208 */ 209 extern "C" 210 JNIEXPORT jint JNICALL Java_sun_jvm_hotspot_debugger_linux_amd64_DwarfParser_getBasePointerOffsetFromCFA 211 (JNIEnv *env, jobject this_obj) { 212 DwarfParser *parser = reinterpret_cast<DwarfParser *>(get_dwarf_context(env, this_obj)); 213 return parser->get_bp_cfa_offset(); 214 } 215 216 /* 217 * Class: sun_jvm_hotspot_debugger_linux_amd64_DwarfParser 218 * Method: isBPOffsetAvailable 219 * Signature: ()Z 220 */ 221 extern "C" 222 JNIEXPORT jboolean JNICALL Java_sun_jvm_hotspot_debugger_linux_amd64_DwarfParser_isBPOffsetAvailable 223 (JNIEnv *env, jobject this_obj) { 224 DwarfParser *parser = reinterpret_cast<DwarfParser *>(get_dwarf_context(env, this_obj)); 225 return parser->is_bp_offset_available(); 226 } 227