agent/src/os/bsd/BsdDebuggerLocal.c

changeset 0
f90c822e73f8
equal deleted inserted replaced
-1:000000000000 0:f90c822e73f8
1 /*
2 * Copyright (c) 2002, 2007, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25 #include <stdlib.h>
26 #include <jni.h>
27 #include "libproc.h"
28
29 #if defined(x86_64) && !defined(amd64)
30 #define amd64 1
31 #endif
32
33 #ifdef i386
34 #include "sun_jvm_hotspot_debugger_x86_X86ThreadContext.h"
35 #endif
36
37 #ifdef amd64
38 #include "sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext.h"
39 #endif
40
41 #if defined(sparc) || defined(sparcv9)
42 #include "sun_jvm_hotspot_debugger_sparc_SPARCThreadContext.h"
43 #endif
44
45 static jfieldID p_ps_prochandle_ID = 0;
46 static jfieldID threadList_ID = 0;
47 static jfieldID loadObjectList_ID = 0;
48
49 static jmethodID createClosestSymbol_ID = 0;
50 static jmethodID createLoadObject_ID = 0;
51 static jmethodID getThreadForThreadId_ID = 0;
52 static jmethodID listAdd_ID = 0;
53
54 #define CHECK_EXCEPTION_(value) if ((*env)->ExceptionOccurred(env)) { return value; }
55 #define CHECK_EXCEPTION if ((*env)->ExceptionOccurred(env)) { return;}
56 #define THROW_NEW_DEBUGGER_EXCEPTION_(str, value) { throw_new_debugger_exception(env, str); return value; }
57 #define THROW_NEW_DEBUGGER_EXCEPTION(str) { throw_new_debugger_exception(env, str); return;}
58
59 static void throw_new_debugger_exception(JNIEnv* env, const char* errMsg) {
60 (*env)->ThrowNew(env, (*env)->FindClass(env, "sun/jvm/hotspot/debugger/DebuggerException"), errMsg);
61 }
62
63 static struct ps_prochandle* get_proc_handle(JNIEnv* env, jobject this_obj) {
64 jlong ptr = (*env)->GetLongField(env, this_obj, p_ps_prochandle_ID);
65 return (struct ps_prochandle*)(intptr_t)ptr;
66 }
67
68 /*
69 * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
70 * Method: init0
71 * Signature: ()V
72 */
73 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_init0
74 (JNIEnv *env, jclass cls) {
75 jclass listClass;
76
77 if (init_libproc(getenv("LIBSAPROC_DEBUG") != NULL) != true) {
78 THROW_NEW_DEBUGGER_EXCEPTION("can't initialize libproc");
79 }
80
81 // fields we use
82 p_ps_prochandle_ID = (*env)->GetFieldID(env, cls, "p_ps_prochandle", "J");
83 CHECK_EXCEPTION;
84 threadList_ID = (*env)->GetFieldID(env, cls, "threadList", "Ljava/util/List;");
85 CHECK_EXCEPTION;
86 loadObjectList_ID = (*env)->GetFieldID(env, cls, "loadObjectList", "Ljava/util/List;");
87 CHECK_EXCEPTION;
88
89 // methods we use
90 createClosestSymbol_ID = (*env)->GetMethodID(env, cls, "createClosestSymbol",
91 "(Ljava/lang/String;J)Lsun/jvm/hotspot/debugger/cdbg/ClosestSymbol;");
92 CHECK_EXCEPTION;
93 createLoadObject_ID = (*env)->GetMethodID(env, cls, "createLoadObject",
94 "(Ljava/lang/String;JJ)Lsun/jvm/hotspot/debugger/cdbg/LoadObject;");
95 CHECK_EXCEPTION;
96 getThreadForThreadId_ID = (*env)->GetMethodID(env, cls, "getThreadForThreadId",
97 "(J)Lsun/jvm/hotspot/debugger/ThreadProxy;");
98 CHECK_EXCEPTION;
99 // java.util.List method we call
100 listClass = (*env)->FindClass(env, "java/util/List");
101 CHECK_EXCEPTION;
102 listAdd_ID = (*env)->GetMethodID(env, listClass, "add", "(Ljava/lang/Object;)Z");
103 CHECK_EXCEPTION;
104 }
105
106 JNIEXPORT jint JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_getAddressSize
107 (JNIEnv *env, jclass cls)
108 {
109 #ifdef _LP64
110 return 8;
111 #else
112 return 4;
113 #endif
114
115 }
116
117
118 static void fillThreadsAndLoadObjects(JNIEnv* env, jobject this_obj, struct ps_prochandle* ph) {
119 int n = 0, i = 0;
120
121 // add threads
122 n = get_num_threads(ph);
123 for (i = 0; i < n; i++) {
124 jobject thread;
125 jobject threadList;
126 lwpid_t lwpid;
127
128 lwpid = get_lwp_id(ph, i);
129 thread = (*env)->CallObjectMethod(env, this_obj, getThreadForThreadId_ID,
130 (jlong)lwpid);
131 CHECK_EXCEPTION;
132 threadList = (*env)->GetObjectField(env, this_obj, threadList_ID);
133 CHECK_EXCEPTION;
134 (*env)->CallBooleanMethod(env, threadList, listAdd_ID, thread);
135 CHECK_EXCEPTION;
136 }
137
138 // add load objects
139 n = get_num_libs(ph);
140 for (i = 0; i < n; i++) {
141 uintptr_t base;
142 const char* name;
143 jobject loadObject;
144 jobject loadObjectList;
145
146 base = get_lib_base(ph, i);
147 name = get_lib_name(ph, i);
148 loadObject = (*env)->CallObjectMethod(env, this_obj, createLoadObject_ID,
149 (*env)->NewStringUTF(env, name), (jlong)0, (jlong)base);
150 CHECK_EXCEPTION;
151 loadObjectList = (*env)->GetObjectField(env, this_obj, loadObjectList_ID);
152 CHECK_EXCEPTION;
153 (*env)->CallBooleanMethod(env, loadObjectList, listAdd_ID, loadObject);
154 CHECK_EXCEPTION;
155 }
156 }
157
158 /*
159 * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
160 * Method: attach0
161 * Signature: (I)V
162 */
163 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_attach0__I
164 (JNIEnv *env, jobject this_obj, jint jpid) {
165
166 struct ps_prochandle* ph;
167 if ( (ph = Pgrab(jpid)) == NULL) {
168 THROW_NEW_DEBUGGER_EXCEPTION("Can't attach to the process");
169 }
170 (*env)->SetLongField(env, this_obj, p_ps_prochandle_ID, (jlong)(intptr_t)ph);
171 fillThreadsAndLoadObjects(env, this_obj, ph);
172 }
173
174 /*
175 * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
176 * Method: attach0
177 * Signature: (Ljava/lang/String;Ljava/lang/String;)V
178 */
179 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_attach0__Ljava_lang_String_2Ljava_lang_String_2
180 (JNIEnv *env, jobject this_obj, jstring execName, jstring coreName) {
181 const char *execName_cstr;
182 const char *coreName_cstr;
183 jboolean isCopy;
184 struct ps_prochandle* ph;
185
186 execName_cstr = (*env)->GetStringUTFChars(env, execName, &isCopy);
187 CHECK_EXCEPTION;
188 coreName_cstr = (*env)->GetStringUTFChars(env, coreName, &isCopy);
189 CHECK_EXCEPTION;
190
191 if ( (ph = Pgrab_core(execName_cstr, coreName_cstr)) == NULL) {
192 (*env)->ReleaseStringUTFChars(env, execName, execName_cstr);
193 (*env)->ReleaseStringUTFChars(env, coreName, coreName_cstr);
194 THROW_NEW_DEBUGGER_EXCEPTION("Can't attach to the core file");
195 }
196 (*env)->SetLongField(env, this_obj, p_ps_prochandle_ID, (jlong)(intptr_t)ph);
197 (*env)->ReleaseStringUTFChars(env, execName, execName_cstr);
198 (*env)->ReleaseStringUTFChars(env, coreName, coreName_cstr);
199 fillThreadsAndLoadObjects(env, this_obj, ph);
200 }
201
202 /*
203 * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
204 * Method: detach0
205 * Signature: ()V
206 */
207 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_detach0
208 (JNIEnv *env, jobject this_obj) {
209 struct ps_prochandle* ph = get_proc_handle(env, this_obj);
210 if (ph != NULL) {
211 Prelease(ph);
212 }
213 }
214
215 /*
216 * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
217 * Method: lookupByName0
218 * Signature: (Ljava/lang/String;Ljava/lang/String;)J
219 */
220 JNIEXPORT jlong JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_lookupByName0
221 (JNIEnv *env, jobject this_obj, jstring objectName, jstring symbolName) {
222 const char *objectName_cstr, *symbolName_cstr;
223 jlong addr;
224 jboolean isCopy;
225 struct ps_prochandle* ph = get_proc_handle(env, this_obj);
226
227 objectName_cstr = NULL;
228 if (objectName != NULL) {
229 objectName_cstr = (*env)->GetStringUTFChars(env, objectName, &isCopy);
230 CHECK_EXCEPTION_(0);
231 }
232 symbolName_cstr = (*env)->GetStringUTFChars(env, symbolName, &isCopy);
233 CHECK_EXCEPTION_(0);
234
235 addr = (jlong) lookup_symbol(ph, objectName_cstr, symbolName_cstr);
236
237 if (objectName_cstr != NULL) {
238 (*env)->ReleaseStringUTFChars(env, objectName, objectName_cstr);
239 }
240 (*env)->ReleaseStringUTFChars(env, symbolName, symbolName_cstr);
241 return addr;
242 }
243
244 /*
245 * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
246 * Method: lookupByAddress0
247 * Signature: (J)Lsun/jvm/hotspot/debugger/cdbg/ClosestSymbol;
248 */
249 JNIEXPORT jobject JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_lookupByAddress0
250 (JNIEnv *env, jobject this_obj, jlong addr) {
251 uintptr_t offset;
252 const char* sym = NULL;
253
254 struct ps_prochandle* ph = get_proc_handle(env, this_obj);
255 sym = symbol_for_pc(ph, (uintptr_t) addr, &offset);
256 if (sym == NULL) return 0;
257 return (*env)->CallObjectMethod(env, this_obj, createClosestSymbol_ID,
258 (*env)->NewStringUTF(env, sym), (jlong)offset);
259 }
260
261 /*
262 * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
263 * Method: readBytesFromProcess0
264 * Signature: (JJ)Lsun/jvm/hotspot/debugger/ReadResult;
265 */
266 JNIEXPORT jbyteArray JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_readBytesFromProcess0
267 (JNIEnv *env, jobject this_obj, jlong addr, jlong numBytes) {
268
269 jboolean isCopy;
270 jbyteArray array;
271 jbyte *bufPtr;
272 ps_err_e err;
273
274 array = (*env)->NewByteArray(env, numBytes);
275 CHECK_EXCEPTION_(0);
276 bufPtr = (*env)->GetByteArrayElements(env, array, &isCopy);
277 CHECK_EXCEPTION_(0);
278
279 err = ps_pread(get_proc_handle(env, this_obj), (psaddr_t) (uintptr_t)addr, bufPtr, numBytes);
280 (*env)->ReleaseByteArrayElements(env, array, bufPtr, 0);
281 return (err == PS_OK)? array : 0;
282 }
283
284 JNIEXPORT jlongArray JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_getThreadIntegerRegisterSet0
285 (JNIEnv *env, jobject this_obj, jint lwp_id) {
286
287 struct reg gregs;
288 jboolean isCopy;
289 jlongArray array;
290 jlong *regs;
291
292 struct ps_prochandle* ph = get_proc_handle(env, this_obj);
293 if (get_lwp_regs(ph, lwp_id, &gregs) != true) {
294 THROW_NEW_DEBUGGER_EXCEPTION_("get_thread_regs failed for a lwp", 0);
295 }
296
297 #undef NPRGREG
298 #ifdef i386
299 #define NPRGREG sun_jvm_hotspot_debugger_x86_X86ThreadContext_NPRGREG
300 #endif
301 #ifdef ia64
302 #define NPRGREG IA64_REG_COUNT
303 #endif
304 #ifdef amd64
305 #define NPRGREG sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_NPRGREG
306 #endif
307 #if defined(sparc) || defined(sparcv9)
308 #define NPRGREG sun_jvm_hotspot_debugger_sparc_SPARCThreadContext_NPRGREG
309 #endif
310
311 array = (*env)->NewLongArray(env, NPRGREG);
312 CHECK_EXCEPTION_(0);
313 regs = (*env)->GetLongArrayElements(env, array, &isCopy);
314
315 #undef REG_INDEX
316
317 #ifdef i386
318 #define REG_INDEX(reg) sun_jvm_hotspot_debugger_x86_X86ThreadContext_##reg
319
320 regs[REG_INDEX(GS)] = (uintptr_t) gregs.r_gs;
321 regs[REG_INDEX(FS)] = (uintptr_t) gregs.r_fs;
322 regs[REG_INDEX(ES)] = (uintptr_t) gregs.r_es;
323 regs[REG_INDEX(DS)] = (uintptr_t) gregs.r_ds;
324 regs[REG_INDEX(EDI)] = (uintptr_t) gregs.r_edi;
325 regs[REG_INDEX(ESI)] = (uintptr_t) gregs.r_esi;
326 regs[REG_INDEX(FP)] = (uintptr_t) gregs.r_ebp;
327 regs[REG_INDEX(SP)] = (uintptr_t) gregs.r_isp;
328 regs[REG_INDEX(EBX)] = (uintptr_t) gregs.r_ebx;
329 regs[REG_INDEX(EDX)] = (uintptr_t) gregs.r_edx;
330 regs[REG_INDEX(ECX)] = (uintptr_t) gregs.r_ecx;
331 regs[REG_INDEX(EAX)] = (uintptr_t) gregs.r_eax;
332 regs[REG_INDEX(PC)] = (uintptr_t) gregs.r_eip;
333 regs[REG_INDEX(CS)] = (uintptr_t) gregs.r_cs;
334 regs[REG_INDEX(SS)] = (uintptr_t) gregs.r_ss;
335
336 #endif /* i386 */
337
338 #if ia64
339 regs = (*env)->GetLongArrayElements(env, array, &isCopy);
340 int i;
341 for (i = 0; i < NPRGREG; i++ ) {
342 regs[i] = 0xDEADDEAD;
343 }
344 #endif /* ia64 */
345
346 #ifdef amd64
347 #define REG_INDEX(reg) sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_##reg
348
349 regs[REG_INDEX(R15)] = gregs.r_r15;
350 regs[REG_INDEX(R14)] = gregs.r_r14;
351 regs[REG_INDEX(R13)] = gregs.r_r13;
352 regs[REG_INDEX(R12)] = gregs.r_r12;
353 regs[REG_INDEX(RBP)] = gregs.r_rbp;
354 regs[REG_INDEX(RBX)] = gregs.r_rbx;
355 regs[REG_INDEX(R11)] = gregs.r_r11;
356 regs[REG_INDEX(R10)] = gregs.r_r10;
357 regs[REG_INDEX(R9)] = gregs.r_r9;
358 regs[REG_INDEX(R8)] = gregs.r_r8;
359 regs[REG_INDEX(RAX)] = gregs.r_rax;
360 regs[REG_INDEX(RCX)] = gregs.r_rcx;
361 regs[REG_INDEX(RDX)] = gregs.r_rdx;
362 regs[REG_INDEX(RSI)] = gregs.r_rsi;
363 regs[REG_INDEX(RDI)] = gregs.r_rdi;
364 regs[REG_INDEX(RIP)] = gregs.r_rip;
365 regs[REG_INDEX(CS)] = gregs.r_cs;
366 regs[REG_INDEX(RSP)] = gregs.r_rsp;
367 regs[REG_INDEX(SS)] = gregs.r_ss;
368 // regs[REG_INDEX(FSBASE)] = gregs.fs_base;
369 // regs[REG_INDEX(GSBASE)] = gregs.gs_base;
370 // regs[REG_INDEX(DS)] = gregs.ds;
371 // regs[REG_INDEX(ES)] = gregs.es;
372 // regs[REG_INDEX(FS)] = gregs.fs;
373 // regs[REG_INDEX(GS)] = gregs.gs;
374
375 #endif /* amd64 */
376
377 #if defined(sparc) || defined(sparcv9)
378
379 #define REG_INDEX(reg) sun_jvm_hotspot_debugger_sparc_SPARCThreadContext_##reg
380
381 #ifdef _LP64
382 regs[REG_INDEX(R_PSR)] = gregs.tstate;
383 regs[REG_INDEX(R_PC)] = gregs.tpc;
384 regs[REG_INDEX(R_nPC)] = gregs.tnpc;
385 regs[REG_INDEX(R_Y)] = gregs.y;
386 #else
387 regs[REG_INDEX(R_PSR)] = gregs.psr;
388 regs[REG_INDEX(R_PC)] = gregs.pc;
389 regs[REG_INDEX(R_nPC)] = gregs.npc;
390 regs[REG_INDEX(R_Y)] = gregs.y;
391 #endif
392 regs[REG_INDEX(R_G0)] = 0 ;
393 regs[REG_INDEX(R_G1)] = gregs.u_regs[0];
394 regs[REG_INDEX(R_G2)] = gregs.u_regs[1];
395 regs[REG_INDEX(R_G3)] = gregs.u_regs[2];
396 regs[REG_INDEX(R_G4)] = gregs.u_regs[3];
397 regs[REG_INDEX(R_G5)] = gregs.u_regs[4];
398 regs[REG_INDEX(R_G6)] = gregs.u_regs[5];
399 regs[REG_INDEX(R_G7)] = gregs.u_regs[6];
400 regs[REG_INDEX(R_O0)] = gregs.u_regs[7];
401 regs[REG_INDEX(R_O1)] = gregs.u_regs[8];
402 regs[REG_INDEX(R_O2)] = gregs.u_regs[ 9];
403 regs[REG_INDEX(R_O3)] = gregs.u_regs[10];
404 regs[REG_INDEX(R_O4)] = gregs.u_regs[11];
405 regs[REG_INDEX(R_O5)] = gregs.u_regs[12];
406 regs[REG_INDEX(R_O6)] = gregs.u_regs[13];
407 regs[REG_INDEX(R_O7)] = gregs.u_regs[14];
408 #endif /* sparc */
409
410
411 (*env)->ReleaseLongArrayElements(env, array, regs, JNI_COMMIT);
412 return array;
413 }

mercurial