Mercurial > hg > truffle
annotate agent/src/os/linux/LinuxDebuggerLocal.c @ 4125:81f7362f7bed
Merge
author | kvn |
---|---|
date | Thu, 08 Dec 2011 10:27:33 -0800 |
parents | c18cbe5936b8 |
children | a9fed06c01d2 |
rev | line source |
---|---|
0 | 1 /* |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
2 * Copyright (c) 2002, 2007, Oracle and/or its affiliates. All rights reserved. |
0 | 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 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
25 #include <jni.h> | |
26 #include "libproc.h" | |
27 | |
28 #if defined(x86_64) && !defined(amd64) | |
29 #define amd64 1 | |
30 #endif | |
31 | |
32 #ifdef i386 | |
33 #include "sun_jvm_hotspot_debugger_x86_X86ThreadContext.h" | |
34 #endif | |
35 | |
36 #ifdef amd64 | |
37 #include "sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext.h" | |
38 #endif | |
39 | |
40 #if defined(sparc) || defined(sparcv9) | |
41 #include "sun_jvm_hotspot_debugger_sparc_SPARCThreadContext.h" | |
42 #endif | |
43 | |
44 static jfieldID p_ps_prochandle_ID = 0; | |
45 static jfieldID threadList_ID = 0; | |
46 static jfieldID loadObjectList_ID = 0; | |
47 | |
48 static jmethodID createClosestSymbol_ID = 0; | |
49 static jmethodID createLoadObject_ID = 0; | |
50 static jmethodID getThreadForThreadId_ID = 0; | |
51 static jmethodID listAdd_ID = 0; | |
52 | |
53 #define CHECK_EXCEPTION_(value) if ((*env)->ExceptionOccurred(env)) { return value; } | |
54 #define CHECK_EXCEPTION if ((*env)->ExceptionOccurred(env)) { return;} | |
55 #define THROW_NEW_DEBUGGER_EXCEPTION_(str, value) { throw_new_debugger_exception(env, str); return value; } | |
56 #define THROW_NEW_DEBUGGER_EXCEPTION(str) { throw_new_debugger_exception(env, str); return;} | |
57 | |
58 static void throw_new_debugger_exception(JNIEnv* env, const char* errMsg) { | |
59 (*env)->ThrowNew(env, (*env)->FindClass(env, "sun/jvm/hotspot/debugger/DebuggerException"), errMsg); | |
60 } | |
61 | |
62 static struct ps_prochandle* get_proc_handle(JNIEnv* env, jobject this_obj) { | |
63 jlong ptr = (*env)->GetLongField(env, this_obj, p_ps_prochandle_ID); | |
64 return (struct ps_prochandle*)(intptr_t)ptr; | |
65 } | |
66 | |
67 /* | |
68 * Class: sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal | |
69 * Method: init0 | |
70 * Signature: ()V | |
71 */ | |
72 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal_init0 | |
73 (JNIEnv *env, jclass cls) { | |
74 jclass listClass; | |
75 | |
76 if (init_libproc(getenv("LIBSAPROC_DEBUG")) != true) { | |
77 THROW_NEW_DEBUGGER_EXCEPTION("can't initialize libproc"); | |
78 } | |
79 | |
80 // fields we use | |
81 p_ps_prochandle_ID = (*env)->GetFieldID(env, cls, "p_ps_prochandle", "J"); | |
82 CHECK_EXCEPTION; | |
83 threadList_ID = (*env)->GetFieldID(env, cls, "threadList", "Ljava/util/List;"); | |
84 CHECK_EXCEPTION; | |
85 loadObjectList_ID = (*env)->GetFieldID(env, cls, "loadObjectList", "Ljava/util/List;"); | |
86 CHECK_EXCEPTION; | |
87 | |
88 // methods we use | |
89 createClosestSymbol_ID = (*env)->GetMethodID(env, cls, "createClosestSymbol", | |
90 "(Ljava/lang/String;J)Lsun/jvm/hotspot/debugger/cdbg/ClosestSymbol;"); | |
91 CHECK_EXCEPTION; | |
92 createLoadObject_ID = (*env)->GetMethodID(env, cls, "createLoadObject", | |
93 "(Ljava/lang/String;JJ)Lsun/jvm/hotspot/debugger/cdbg/LoadObject;"); | |
94 CHECK_EXCEPTION; | |
95 getThreadForThreadId_ID = (*env)->GetMethodID(env, cls, "getThreadForThreadId", | |
96 "(J)Lsun/jvm/hotspot/debugger/ThreadProxy;"); | |
97 CHECK_EXCEPTION; | |
98 // java.util.List method we call | |
99 listClass = (*env)->FindClass(env, "java/util/List"); | |
100 CHECK_EXCEPTION; | |
101 listAdd_ID = (*env)->GetMethodID(env, listClass, "add", "(Ljava/lang/Object;)Z"); | |
102 CHECK_EXCEPTION; | |
103 } | |
104 | |
105 JNIEXPORT jint JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal_getAddressSize | |
106 (JNIEnv *env, jclass cls) | |
107 { | |
108 #ifdef _LP64 | |
109 return 8; | |
110 #else | |
111 return 4; | |
112 #endif | |
113 | |
114 } | |
115 | |
116 | |
117 static void fillThreadsAndLoadObjects(JNIEnv* env, jobject this_obj, struct ps_prochandle* ph) { | |
118 int n = 0, i = 0; | |
119 | |
120 // add threads | |
121 n = get_num_threads(ph); | |
122 for (i = 0; i < n; i++) { | |
123 jobject thread; | |
124 jobject threadList; | |
125 lwpid_t lwpid; | |
126 | |
127 lwpid = get_lwp_id(ph, i); | |
128 thread = (*env)->CallObjectMethod(env, this_obj, getThreadForThreadId_ID, | |
129 (jlong)lwpid); | |
130 CHECK_EXCEPTION; | |
131 threadList = (*env)->GetObjectField(env, this_obj, threadList_ID); | |
132 CHECK_EXCEPTION; | |
133 (*env)->CallBooleanMethod(env, threadList, listAdd_ID, thread); | |
134 CHECK_EXCEPTION; | |
135 } | |
136 | |
137 // add load objects | |
138 n = get_num_libs(ph); | |
139 for (i = 0; i < n; i++) { | |
140 uintptr_t base; | |
141 const char* name; | |
142 jobject loadObject; | |
143 jobject loadObjectList; | |
144 | |
145 base = get_lib_base(ph, i); | |
146 name = get_lib_name(ph, i); | |
147 loadObject = (*env)->CallObjectMethod(env, this_obj, createLoadObject_ID, | |
148 (*env)->NewStringUTF(env, name), (jlong)0, (jlong)base); | |
149 CHECK_EXCEPTION; | |
150 loadObjectList = (*env)->GetObjectField(env, this_obj, loadObjectList_ID); | |
151 CHECK_EXCEPTION; | |
152 (*env)->CallBooleanMethod(env, loadObjectList, listAdd_ID, loadObject); | |
153 CHECK_EXCEPTION; | |
154 } | |
155 } | |
156 | |
157 /* | |
158 * Class: sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal | |
159 * Method: attach0 | |
160 * Signature: (I)V | |
161 */ | |
162 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal_attach0__I | |
163 (JNIEnv *env, jobject this_obj, jint jpid) { | |
164 | |
165 struct ps_prochandle* ph; | |
166 if ( (ph = Pgrab(jpid)) == NULL) { | |
167 THROW_NEW_DEBUGGER_EXCEPTION("Can't attach to the process"); | |
168 } | |
169 (*env)->SetLongField(env, this_obj, p_ps_prochandle_ID, (jlong)(intptr_t)ph); | |
170 fillThreadsAndLoadObjects(env, this_obj, ph); | |
171 } | |
172 | |
173 /* | |
174 * Class: sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal | |
175 * Method: attach0 | |
176 * Signature: (Ljava/lang/String;Ljava/lang/String;)V | |
177 */ | |
178 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal_attach0__Ljava_lang_String_2Ljava_lang_String_2 | |
179 (JNIEnv *env, jobject this_obj, jstring execName, jstring coreName) { | |
180 const char *execName_cstr; | |
181 const char *coreName_cstr; | |
182 jboolean isCopy; | |
183 struct ps_prochandle* ph; | |
184 | |
185 execName_cstr = (*env)->GetStringUTFChars(env, execName, &isCopy); | |
186 CHECK_EXCEPTION; | |
187 coreName_cstr = (*env)->GetStringUTFChars(env, coreName, &isCopy); | |
188 CHECK_EXCEPTION; | |
189 | |
190 if ( (ph = Pgrab_core(execName_cstr, coreName_cstr)) == NULL) { | |
191 (*env)->ReleaseStringUTFChars(env, execName, execName_cstr); | |
192 (*env)->ReleaseStringUTFChars(env, coreName, coreName_cstr); | |
193 THROW_NEW_DEBUGGER_EXCEPTION("Can't attach to the core file"); | |
194 } | |
195 (*env)->SetLongField(env, this_obj, p_ps_prochandle_ID, (jlong)(intptr_t)ph); | |
196 (*env)->ReleaseStringUTFChars(env, execName, execName_cstr); | |
197 (*env)->ReleaseStringUTFChars(env, coreName, coreName_cstr); | |
198 fillThreadsAndLoadObjects(env, this_obj, ph); | |
199 } | |
200 | |
201 /* | |
202 * Class: sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal | |
203 * Method: detach0 | |
204 * Signature: ()V | |
205 */ | |
206 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal_detach0 | |
207 (JNIEnv *env, jobject this_obj) { | |
208 struct ps_prochandle* ph = get_proc_handle(env, this_obj); | |
209 if (ph != NULL) { | |
210 Prelease(ph); | |
211 } | |
212 } | |
213 | |
214 /* | |
215 * Class: sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal | |
216 * Method: lookupByName0 | |
217 * Signature: (Ljava/lang/String;Ljava/lang/String;)J | |
218 */ | |
219 JNIEXPORT jlong JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal_lookupByName0 | |
220 (JNIEnv *env, jobject this_obj, jstring objectName, jstring symbolName) { | |
221 const char *objectName_cstr, *symbolName_cstr; | |
222 jlong addr; | |
223 jboolean isCopy; | |
224 struct ps_prochandle* ph = get_proc_handle(env, this_obj); | |
225 | |
226 objectName_cstr = NULL; | |
227 if (objectName != NULL) { | |
228 objectName_cstr = (*env)->GetStringUTFChars(env, objectName, &isCopy); | |
229 CHECK_EXCEPTION_(0); | |
230 } | |
231 symbolName_cstr = (*env)->GetStringUTFChars(env, symbolName, &isCopy); | |
232 CHECK_EXCEPTION_(0); | |
233 | |
234 addr = (jlong) lookup_symbol(ph, objectName_cstr, symbolName_cstr); | |
235 | |
236 if (objectName_cstr != NULL) { | |
237 (*env)->ReleaseStringUTFChars(env, objectName, objectName_cstr); | |
238 } | |
239 (*env)->ReleaseStringUTFChars(env, symbolName, symbolName_cstr); | |
240 return addr; | |
241 } | |
242 | |
243 /* | |
244 * Class: sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal | |
245 * Method: lookupByAddress0 | |
246 * Signature: (J)Lsun/jvm/hotspot/debugger/cdbg/ClosestSymbol; | |
247 */ | |
248 JNIEXPORT jobject JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal_lookupByAddress0 | |
249 (JNIEnv *env, jobject this_obj, jlong addr) { | |
250 uintptr_t offset; | |
251 const char* sym = NULL; | |
252 | |
253 struct ps_prochandle* ph = get_proc_handle(env, this_obj); | |
254 sym = symbol_for_pc(ph, (uintptr_t) addr, &offset); | |
255 if (sym == NULL) return 0; | |
256 return (*env)->CallObjectMethod(env, this_obj, createClosestSymbol_ID, | |
257 (*env)->NewStringUTF(env, sym), (jlong)offset); | |
258 } | |
259 | |
260 /* | |
261 * Class: sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal | |
262 * Method: readBytesFromProcess0 | |
263 * Signature: (JJ)Lsun/jvm/hotspot/debugger/ReadResult; | |
264 */ | |
265 JNIEXPORT jbyteArray JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal_readBytesFromProcess0 | |
266 (JNIEnv *env, jobject this_obj, jlong addr, jlong numBytes) { | |
267 | |
268 jboolean isCopy; | |
269 jbyteArray array; | |
270 jbyte *bufPtr; | |
271 ps_err_e err; | |
272 | |
273 array = (*env)->NewByteArray(env, numBytes); | |
274 CHECK_EXCEPTION_(0); | |
275 bufPtr = (*env)->GetByteArrayElements(env, array, &isCopy); | |
276 CHECK_EXCEPTION_(0); | |
277 | |
278 err = ps_pdread(get_proc_handle(env, this_obj), (psaddr_t) (uintptr_t)addr, bufPtr, numBytes); | |
279 (*env)->ReleaseByteArrayElements(env, array, bufPtr, 0); | |
280 return (err == PS_OK)? array : 0; | |
281 } | |
282 | |
283 JNIEXPORT jlongArray JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal_getThreadIntegerRegisterSet0 | |
284 (JNIEnv *env, jobject this_obj, jint lwp_id) { | |
285 | |
286 struct user_regs_struct gregs; | |
287 jboolean isCopy; | |
288 jlongArray array; | |
289 jlong *regs; | |
290 int i; | |
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.xgs; | |
321 regs[REG_INDEX(FS)] = (uintptr_t) gregs.xfs; | |
322 regs[REG_INDEX(ES)] = (uintptr_t) gregs.xes; | |
323 regs[REG_INDEX(DS)] = (uintptr_t) gregs.xds; | |
324 regs[REG_INDEX(EDI)] = (uintptr_t) gregs.edi; | |
325 regs[REG_INDEX(ESI)] = (uintptr_t) gregs.esi; | |
326 regs[REG_INDEX(FP)] = (uintptr_t) gregs.ebp; | |
327 regs[REG_INDEX(SP)] = (uintptr_t) gregs.esp; | |
328 regs[REG_INDEX(EBX)] = (uintptr_t) gregs.ebx; | |
329 regs[REG_INDEX(EDX)] = (uintptr_t) gregs.edx; | |
330 regs[REG_INDEX(ECX)] = (uintptr_t) gregs.ecx; | |
331 regs[REG_INDEX(EAX)] = (uintptr_t) gregs.eax; | |
332 regs[REG_INDEX(PC)] = (uintptr_t) gregs.eip; | |
333 regs[REG_INDEX(CS)] = (uintptr_t) gregs.xcs; | |
334 regs[REG_INDEX(SS)] = (uintptr_t) gregs.xss; | |
335 | |
336 #endif /* i386 */ | |
337 | |
338 #if ia64 | |
339 regs = (*env)->GetLongArrayElements(env, array, &isCopy); | |
340 for (i = 0; i < NPRGREG; i++ ) { | |
341 regs[i] = 0xDEADDEAD; | |
342 } | |
343 #endif /* ia64 */ | |
344 | |
345 #ifdef amd64 | |
346 #define REG_INDEX(reg) sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_##reg | |
347 | |
348 regs[REG_INDEX(R15)] = gregs.r15; | |
349 regs[REG_INDEX(R14)] = gregs.r14; | |
350 regs[REG_INDEX(R13)] = gregs.r13; | |
351 regs[REG_INDEX(R12)] = gregs.r12; | |
352 regs[REG_INDEX(RBP)] = gregs.rbp; | |
353 regs[REG_INDEX(RBX)] = gregs.rbx; | |
354 regs[REG_INDEX(R11)] = gregs.r11; | |
355 regs[REG_INDEX(R10)] = gregs.r10; | |
356 regs[REG_INDEX(R9)] = gregs.r9; | |
357 regs[REG_INDEX(R8)] = gregs.r8; | |
358 regs[REG_INDEX(RAX)] = gregs.rax; | |
359 regs[REG_INDEX(RCX)] = gregs.rcx; | |
360 regs[REG_INDEX(RDX)] = gregs.rdx; | |
361 regs[REG_INDEX(RSI)] = gregs.rsi; | |
362 regs[REG_INDEX(RDI)] = gregs.rdi; | |
363 regs[REG_INDEX(RIP)] = gregs.rip; | |
364 regs[REG_INDEX(CS)] = gregs.cs; | |
365 regs[REG_INDEX(RSP)] = gregs.rsp; | |
366 regs[REG_INDEX(SS)] = gregs.ss; | |
367 regs[REG_INDEX(FSBASE)] = gregs.fs_base; | |
368 regs[REG_INDEX(GSBASE)] = gregs.gs_base; | |
369 regs[REG_INDEX(DS)] = gregs.ds; | |
370 regs[REG_INDEX(ES)] = gregs.es; | |
371 regs[REG_INDEX(FS)] = gregs.fs; | |
372 regs[REG_INDEX(GS)] = gregs.gs; | |
373 | |
374 #endif /* amd64 */ | |
375 | |
376 #if defined(sparc) || defined(sparcv9) | |
377 | |
378 #define REG_INDEX(reg) sun_jvm_hotspot_debugger_sparc_SPARCThreadContext_##reg | |
379 | |
380 #ifdef _LP64 | |
381 regs[REG_INDEX(R_PSR)] = gregs.tstate; | |
382 regs[REG_INDEX(R_PC)] = gregs.tpc; | |
383 regs[REG_INDEX(R_nPC)] = gregs.tnpc; | |
384 regs[REG_INDEX(R_Y)] = gregs.y; | |
385 #else | |
386 regs[REG_INDEX(R_PSR)] = gregs.psr; | |
387 regs[REG_INDEX(R_PC)] = gregs.pc; | |
388 regs[REG_INDEX(R_nPC)] = gregs.npc; | |
389 regs[REG_INDEX(R_Y)] = gregs.y; | |
390 #endif | |
391 regs[REG_INDEX(R_G0)] = 0 ; | |
392 regs[REG_INDEX(R_G1)] = gregs.u_regs[0]; | |
393 regs[REG_INDEX(R_G2)] = gregs.u_regs[1]; | |
394 regs[REG_INDEX(R_G3)] = gregs.u_regs[2]; | |
395 regs[REG_INDEX(R_G4)] = gregs.u_regs[3]; | |
396 regs[REG_INDEX(R_G5)] = gregs.u_regs[4]; | |
397 regs[REG_INDEX(R_G6)] = gregs.u_regs[5]; | |
398 regs[REG_INDEX(R_G7)] = gregs.u_regs[6]; | |
399 regs[REG_INDEX(R_O0)] = gregs.u_regs[7]; | |
400 regs[REG_INDEX(R_O1)] = gregs.u_regs[8]; | |
401 regs[REG_INDEX(R_O2)] = gregs.u_regs[ 9]; | |
402 regs[REG_INDEX(R_O3)] = gregs.u_regs[10]; | |
403 regs[REG_INDEX(R_O4)] = gregs.u_regs[11]; | |
404 regs[REG_INDEX(R_O5)] = gregs.u_regs[12]; | |
405 regs[REG_INDEX(R_O6)] = gregs.u_regs[13]; | |
406 regs[REG_INDEX(R_O7)] = gregs.u_regs[14]; | |
407 #endif /* sparc */ | |
408 | |
409 | |
410 (*env)->ReleaseLongArrayElements(env, array, regs, JNI_COMMIT); | |
411 return array; | |
412 } |