1 /*
2 * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
3 * Copyright (c) 2020, 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
get_dwarf_context(JNIEnv * env,jobject obj)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"
Java_sun_jvm_hotspot_debugger_linux_amd64_DwarfParser_init0(JNIEnv * env,jclass this_cls)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"
Java_sun_jvm_hotspot_debugger_linux_amd64_DwarfParser_createDwarfContext(JNIEnv * env,jclass this_cls,jlong lib)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->is_parseable()) {
106 jclass ex_cls = env->FindClass("sun/jvm/hotspot/debugger/DebuggerException");
107 if (!env->ExceptionOccurred()) {
108 env->ThrowNew(ex_cls, "DWARF not found");
109 }
110 return 0L;
111 }
112
113 return reinterpret_cast<jlong>(parser);
114 }
115
116 /*
117 * Class: sun_jvm_hotspot_debugger_linux_amd64_DwarfParser
118 * Method: destroyDwarfContext
119 * Signature: (J)V
120 */
121 extern "C"
Java_sun_jvm_hotspot_debugger_linux_amd64_DwarfParser_destroyDwarfContext(JNIEnv * env,jclass this_cls,jlong context)122 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_linux_amd64_DwarfParser_destroyDwarfContext
123 (JNIEnv *env, jclass this_cls, jlong context) {
124 DwarfParser *parser = reinterpret_cast<DwarfParser *>(context);
125 delete parser;
126 }
127
128 /*
129 * Class: sun_jvm_hotspot_debugger_linux_amd64_DwarfParser
130 * Method: isIn0
131 * Signature: (J)Z
132 */
133 extern "C"
Java_sun_jvm_hotspot_debugger_linux_amd64_DwarfParser_isIn0(JNIEnv * env,jobject this_obj,jlong pc)134 JNIEXPORT jboolean JNICALL Java_sun_jvm_hotspot_debugger_linux_amd64_DwarfParser_isIn0
135 (JNIEnv *env, jobject this_obj, jlong pc) {
136 DwarfParser *parser = reinterpret_cast<DwarfParser *>(get_dwarf_context(env, this_obj));
137 return static_cast<jboolean>(parser->is_in(pc));
138 }
139
140 /*
141 * Class: sun_jvm_hotspot_debugger_linux_amd64_DwarfParser
142 * Method: processDwarf0
143 * Signature: (J)V
144 */
145 extern "C"
Java_sun_jvm_hotspot_debugger_linux_amd64_DwarfParser_processDwarf0(JNIEnv * env,jobject this_obj,jlong pc)146 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_linux_amd64_DwarfParser_processDwarf0
147 (JNIEnv *env, jobject this_obj, jlong pc) {
148 DwarfParser *parser = reinterpret_cast<DwarfParser *>(get_dwarf_context(env, this_obj));
149 if (!parser->process_dwarf(pc)) {
150 jclass ex_cls = env->FindClass("sun/jvm/hotspot/debugger/DebuggerException");
151 if (!env->ExceptionOccurred()) {
152 env->ThrowNew(ex_cls, "Could not find PC in DWARF");
153 }
154 return;
155 }
156 }
157
158 /*
159 * Class: sun_jvm_hotspot_debugger_linux_amd64_DwarfParser
160 * Method: getCFARegister
161 * Signature: ()I
162 */
163 extern "C"
Java_sun_jvm_hotspot_debugger_linux_amd64_DwarfParser_getCFARegister(JNIEnv * env,jobject this_obj)164 JNIEXPORT jint JNICALL Java_sun_jvm_hotspot_debugger_linux_amd64_DwarfParser_getCFARegister
165 (JNIEnv *env, jobject this_obj) {
166 DwarfParser *parser = reinterpret_cast<DwarfParser *>(get_dwarf_context(env, this_obj));
167 switch (parser->get_cfa_register()) {
168 case RAX: return sa_RAX;
169 case RDX: return sa_RDX;
170 case RCX: return sa_RCX;
171 case RBX: return sa_RBX;
172 case RSI: return sa_RSI;
173 case RDI: return sa_RDI;
174 case RBP: return sa_RBP;
175 case RSP: return sa_RSP;
176 case R8: return sa_R8;
177 case R9: return sa_R9;
178 case R10: return sa_R10;
179 case R11: return sa_R11;
180 case R12: return sa_R12;
181 case R13: return sa_R13;
182 case R14: return sa_R14;
183 case R15: return sa_R15;
184 default: return -1;
185 }
186 }
187
188 /*
189 * Class: sun_jvm_hotspot_debugger_linux_amd64_DwarfParser
190 * Method: getCFAOffset
191 * Signature: ()I
192 */
193 extern "C"
Java_sun_jvm_hotspot_debugger_linux_amd64_DwarfParser_getCFAOffset(JNIEnv * env,jobject this_obj)194 JNIEXPORT jint JNICALL Java_sun_jvm_hotspot_debugger_linux_amd64_DwarfParser_getCFAOffset
195 (JNIEnv *env, jobject this_obj) {
196 DwarfParser *parser = reinterpret_cast<DwarfParser *>(get_dwarf_context(env, this_obj));
197 return parser->get_cfa_offset();
198 }
199
200 /*
201 * Class: sun_jvm_hotspot_debugger_linux_amd64_DwarfParser
202 * Method: getReturnAddressOffsetFromCFA
203 * Signature: ()I
204 */
205 extern "C"
Java_sun_jvm_hotspot_debugger_linux_amd64_DwarfParser_getReturnAddressOffsetFromCFA(JNIEnv * env,jobject this_obj)206 JNIEXPORT jint JNICALL Java_sun_jvm_hotspot_debugger_linux_amd64_DwarfParser_getReturnAddressOffsetFromCFA
207 (JNIEnv *env, jobject this_obj) {
208 DwarfParser *parser = reinterpret_cast<DwarfParser *>(get_dwarf_context(env, this_obj));
209 return parser->get_ra_cfa_offset();
210 }
211
212 /*
213 * Class: sun_jvm_hotspot_debugger_linux_amd64_DwarfParser
214 * Method: getBasePointerOffsetFromCFA
215 * Signature: ()I
216 */
217 extern "C"
Java_sun_jvm_hotspot_debugger_linux_amd64_DwarfParser_getBasePointerOffsetFromCFA(JNIEnv * env,jobject this_obj)218 JNIEXPORT jint JNICALL Java_sun_jvm_hotspot_debugger_linux_amd64_DwarfParser_getBasePointerOffsetFromCFA
219 (JNIEnv *env, jobject this_obj) {
220 DwarfParser *parser = reinterpret_cast<DwarfParser *>(get_dwarf_context(env, this_obj));
221 return parser->get_bp_cfa_offset();
222 }
223
224 /*
225 * Class: sun_jvm_hotspot_debugger_linux_amd64_DwarfParser
226 * Method: isBPOffsetAvailable
227 * Signature: ()Z
228 */
229 extern "C"
Java_sun_jvm_hotspot_debugger_linux_amd64_DwarfParser_isBPOffsetAvailable(JNIEnv * env,jobject this_obj)230 JNIEXPORT jboolean JNICALL Java_sun_jvm_hotspot_debugger_linux_amd64_DwarfParser_isBPOffsetAvailable
231 (JNIEnv *env, jobject this_obj) {
232 DwarfParser *parser = reinterpret_cast<DwarfParser *>(get_dwarf_context(env, this_obj));
233 return parser->is_bp_offset_available();
234 }
235
236