comparison agent/src/os/bsd/MacosxDebuggerLocal.m @ 8750:39432a1cefdd

8003348: SA can not read core file on OS Summary: Macosx uses Mach-O file format for binary files, not ELF format. Currently SA works on core files on other platforms, t his change enables SA work on core file generated on Darwin. Reviewed-by: sla, sspitsyn Contributed-by: yumin.qi@oracle.com
author minqi
date Thu, 14 Mar 2013 00:33:08 -0700
parents 40b7c6b800ab
children 9f96b7a853bc
comparison
equal deleted inserted replaced
8719:c8b31b461e1a 8750:39432a1cefdd
1 /* 1 /*
2 * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved. 2 * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 * 4 *
5 * This code is free software; you can redistribute it and/or modify it 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 6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. 7 * published by the Free Software Foundation.
38 #import <dlfcn.h> 38 #import <dlfcn.h>
39 #import <limits.h> 39 #import <limits.h>
40 #import <errno.h> 40 #import <errno.h>
41 #import <sys/types.h> 41 #import <sys/types.h>
42 #import <sys/ptrace.h> 42 #import <sys/ptrace.h>
43 43 #include "libproc_impl.h"
44 jboolean debug = JNI_FALSE; 44
45 #define UNSUPPORTED_ARCH "Unsupported architecture!"
46
47 #if defined(x86_64) && !defined(amd64)
48 #define amd64 1
49 #endif
50
51 #if amd64
52 #include "sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext.h"
53 #else
54 #error UNSUPPORTED_ARCH
55 #endif
45 56
46 static jfieldID symbolicatorID = 0; // set in _init0 57 static jfieldID symbolicatorID = 0; // set in _init0
47 static jfieldID taskID = 0; // set in _init0 58 static jfieldID taskID = 0; // set in _init0
59
60 static jfieldID p_ps_prochandle_ID = 0;
61 static jfieldID loadObjectList_ID = 0;
62 static jmethodID listAdd_ID = 0;
63
64 static jmethodID createClosestSymbol_ID = 0;
65 static jmethodID createLoadObject_ID = 0;
66 static jmethodID getJavaThreadsInfo_ID = 0;
67
68 // indicator if thread id (lwpid_t) was set
69 static bool _threads_filled = false;
48 70
49 static void putSymbolicator(JNIEnv *env, jobject this_obj, id symbolicator) { 71 static void putSymbolicator(JNIEnv *env, jobject this_obj, id symbolicator) {
50 (*env)->SetLongField(env, this_obj, symbolicatorID, (jlong)(intptr_t)symbolicator); 72 (*env)->SetLongField(env, this_obj, symbolicatorID, (jlong)(intptr_t)symbolicator);
51 } 73 }
52 74
72 #define CHECK_EXCEPTION_CLEAR_VOID if ((*env)->ExceptionOccurred(env)) { (*env)->ExceptionClear(env); return; } 94 #define CHECK_EXCEPTION_CLEAR_VOID if ((*env)->ExceptionOccurred(env)) { (*env)->ExceptionClear(env); return; }
73 #define CHECK_EXCEPTION_CLEAR_(value) if ((*env)->ExceptionOccurred(env)) { (*env)->ExceptionClear(env); return value; } 95 #define CHECK_EXCEPTION_CLEAR_(value) if ((*env)->ExceptionOccurred(env)) { (*env)->ExceptionClear(env); return value; }
74 96
75 static void throw_new_debugger_exception(JNIEnv* env, const char* errMsg) { 97 static void throw_new_debugger_exception(JNIEnv* env, const char* errMsg) {
76 (*env)->ThrowNew(env, (*env)->FindClass(env, "sun/jvm/hotspot/debugger/DebuggerException"), errMsg); 98 (*env)->ThrowNew(env, (*env)->FindClass(env, "sun/jvm/hotspot/debugger/DebuggerException"), errMsg);
99 }
100
101 static struct ps_prochandle* get_proc_handle(JNIEnv* env, jobject this_obj) {
102 jlong ptr = (*env)->GetLongField(env, this_obj, p_ps_prochandle_ID);
103 return (struct ps_prochandle*)(intptr_t)ptr;
77 } 104 }
78 105
79 #if defined(__i386__) 106 #if defined(__i386__)
80 #define hsdb_thread_state_t x86_thread_state32_t 107 #define hsdb_thread_state_t x86_thread_state32_t
81 #define hsdb_float_state_t x86_float_state32_t 108 #define hsdb_float_state_t x86_float_state32_t
89 #define HSDB_THREAD_STATE x86_THREAD_STATE64 116 #define HSDB_THREAD_STATE x86_THREAD_STATE64
90 #define HSDB_FLOAT_STATE x86_FLOAT_STATE64 117 #define HSDB_FLOAT_STATE x86_FLOAT_STATE64
91 #define HSDB_THREAD_STATE_COUNT x86_THREAD_STATE64_COUNT 118 #define HSDB_THREAD_STATE_COUNT x86_THREAD_STATE64_COUNT
92 #define HSDB_FLOAT_STATE_COUNT x86_FLOAT_STATE64_COUNT 119 #define HSDB_FLOAT_STATE_COUNT x86_FLOAT_STATE64_COUNT
93 #else 120 #else
94 #error "Unsupported architecture" 121 #error UNSUPPORTED_ARCH
95 #endif 122 #endif
96 123
97 /* 124 /*
98 * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal 125 * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
99 * Method: init0 126 * Method: init0
102 JNIEXPORT void JNICALL 129 JNIEXPORT void JNICALL
103 Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_init0(JNIEnv *env, jclass cls) { 130 Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_init0(JNIEnv *env, jclass cls) {
104 symbolicatorID = (*env)->GetFieldID(env, cls, "symbolicator", "J"); 131 symbolicatorID = (*env)->GetFieldID(env, cls, "symbolicator", "J");
105 taskID = (*env)->GetFieldID(env, cls, "task", "J"); 132 taskID = (*env)->GetFieldID(env, cls, "task", "J");
106 CHECK_EXCEPTION; 133 CHECK_EXCEPTION;
134
135 // for core file
136 p_ps_prochandle_ID = (*env)->GetFieldID(env, cls, "p_ps_prochandle", "J");
137 CHECK_EXCEPTION;
138 loadObjectList_ID = (*env)->GetFieldID(env, cls, "loadObjectList", "Ljava/util/List;");
139 CHECK_EXCEPTION;
140
141 // methods we use
142 createClosestSymbol_ID = (*env)->GetMethodID(env, cls, "createClosestSymbol",
143 "(Ljava/lang/String;J)Lsun/jvm/hotspot/debugger/cdbg/ClosestSymbol;");
144 CHECK_EXCEPTION;
145 createLoadObject_ID = (*env)->GetMethodID(env, cls, "createLoadObject",
146 "(Ljava/lang/String;JJ)Lsun/jvm/hotspot/debugger/cdbg/LoadObject;");
147 CHECK_EXCEPTION;
148
149 // java.util.List method we call
150 jclass listClass = (*env)->FindClass(env, "java/util/List");
151 CHECK_EXCEPTION;
152 listAdd_ID = (*env)->GetMethodID(env, listClass, "add", "(Ljava/lang/Object;)Z");
153 CHECK_EXCEPTION;
154 getJavaThreadsInfo_ID = (*env)->GetMethodID(env, cls, "getJavaThreadsInfo",
155 "()[J");
156 CHECK_EXCEPTION;
157
158 init_libproc(getenv("LIBSAPROC_DEBUG") != NULL);
159 }
160
161 JNIEXPORT jint JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_getAddressSize
162 (JNIEnv *env, jclass cls)
163 {
164 #ifdef _LP64
165 return 8;
166 #else
167 #error UNSUPPORTED_ARCH
168 #endif
169 }
170
171 /** called by Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_lookupByName0 */
172 jlong lookupByNameIncore(
173 JNIEnv *env, struct ps_prochandle *ph, jobject this_obj, jstring objectName, jstring symbolName)
174 {
175 const char *objectName_cstr, *symbolName_cstr;
176 jlong addr;
177 jboolean isCopy;
178 objectName_cstr = NULL;
179 if (objectName != NULL) {
180 objectName_cstr = (*env)->GetStringUTFChars(env, objectName, &isCopy);
181 CHECK_EXCEPTION_(0);
182 }
183 symbolName_cstr = (*env)->GetStringUTFChars(env, symbolName, &isCopy);
184 CHECK_EXCEPTION_(0);
185
186 print_debug("look for %s \n", symbolName_cstr);
187 addr = (jlong) lookup_symbol(ph, objectName_cstr, symbolName_cstr);
188
189 if (objectName_cstr != NULL) {
190 (*env)->ReleaseStringUTFChars(env, objectName, objectName_cstr);
191 }
192 (*env)->ReleaseStringUTFChars(env, symbolName, symbolName_cstr);
193 return addr;
107 } 194 }
108 195
109 /* 196 /*
110 * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal 197 * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
111 * Method: lookupByName0 198 * Method: lookupByName0
114 JNIEXPORT jlong JNICALL 201 JNIEXPORT jlong JNICALL
115 Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_lookupByName0( 202 Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_lookupByName0(
116 JNIEnv *env, jobject this_obj, 203 JNIEnv *env, jobject this_obj,
117 jstring objectName, jstring symbolName) 204 jstring objectName, jstring symbolName)
118 { 205 {
206 struct ps_prochandle* ph = get_proc_handle(env, this_obj);
207 if (ph->core != NULL) {
208 return lookupByNameIncore(env, ph, this_obj, objectName, symbolName);
209 }
210
119 jlong address = 0; 211 jlong address = 0;
120 212
121 JNF_COCOA_ENTER(env); 213 JNF_COCOA_ENTER(env);
122 NSString *symbolNameString = JNFJavaToNSString(env, symbolName); 214 NSString *symbolNameString = JNFJavaToNSString(env, symbolName);
123 215
124 if (debug) { 216 print_debug("lookupInProcess called for %s\n", [symbolNameString UTF8String]);
125 printf("lookupInProcess called for %s\n", [symbolNameString UTF8String]);
126 }
127 217
128 id symbolicator = getSymbolicator(env, this_obj); 218 id symbolicator = getSymbolicator(env, this_obj);
129 if (symbolicator != nil) { 219 if (symbolicator != nil) {
130 uint64_t (*dynamicCall)(id, SEL, NSString *) = (uint64_t (*)(id, SEL, NSString *))&objc_msgSend; 220 uint64_t (*dynamicCall)(id, SEL, NSString *) = (uint64_t (*)(id, SEL, NSString *))&objc_msgSend;
131 address = (jlong) dynamicCall(symbolicator, @selector(addressForSymbol:), symbolNameString); 221 address = (jlong) dynamicCall(symbolicator, @selector(addressForSymbol:), symbolNameString);
132 } 222 }
133 223
134 if (debug) { 224 print_debug("address of symbol %s = %llx\n", [symbolNameString UTF8String], address);
135 printf("address of symbol %s = %llx\n", [symbolNameString UTF8String], address);
136 }
137 JNF_COCOA_EXIT(env); 225 JNF_COCOA_EXIT(env);
138 226
139 return address; 227 return address;
228 }
229
230 /*
231 * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
232 * Method: lookupByAddress0
233 * Signature: (J)Lsun/jvm/hotspot/debugger/cdbg/ClosestSymbol;
234 */
235 JNIEXPORT jobject JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_lookupByAddress0
236 (JNIEnv *env, jobject this_obj, jlong addr) {
237 uintptr_t offset;
238 const char* sym = NULL;
239
240 struct ps_prochandle* ph = get_proc_handle(env, this_obj);
241 sym = symbol_for_pc(ph, (uintptr_t) addr, &offset);
242 if (sym == NULL) return 0;
243 return (*env)->CallObjectMethod(env, this_obj, createClosestSymbol_ID,
244 (*env)->NewStringUTF(env, sym), (jlong)offset);
245 }
246
247 /** called from Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_readBytesFromProcess0 */
248 jbyteArray readBytesFromCore(
249 JNIEnv *env, struct ps_prochandle *ph, jobject this_obj, jlong addr, jlong numBytes)
250 {
251 jboolean isCopy;
252 jbyteArray array;
253 jbyte *bufPtr;
254 ps_err_e err;
255
256 array = (*env)->NewByteArray(env, numBytes);
257 CHECK_EXCEPTION_(0);
258 bufPtr = (*env)->GetByteArrayElements(env, array, &isCopy);
259 CHECK_EXCEPTION_(0);
260
261 err = ps_pread(ph, (psaddr_t) (uintptr_t)addr, bufPtr, numBytes);
262 (*env)->ReleaseByteArrayElements(env, array, bufPtr, 0);
263 return (err == PS_OK)? array : 0;
140 } 264 }
141 265
142 /* 266 /*
143 * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal 267 * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
144 * Method: readBytesFromProcess0 268 * Method: readBytesFromProcess0
147 JNIEXPORT jbyteArray JNICALL 271 JNIEXPORT jbyteArray JNICALL
148 Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_readBytesFromProcess0( 272 Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_readBytesFromProcess0(
149 JNIEnv *env, jobject this_obj, 273 JNIEnv *env, jobject this_obj,
150 jlong addr, jlong numBytes) 274 jlong addr, jlong numBytes)
151 { 275 {
152 if (debug) printf("readBytesFromProcess called. addr = %llx numBytes = %lld\n", addr, numBytes); 276 print_debug("readBytesFromProcess called. addr = %llx numBytes = %lld\n", addr, numBytes);
153 277
154 // must allocate storage instead of using former parameter buf 278 // must allocate storage instead of using former parameter buf
155 jboolean isCopy;
156 jbyteArray array; 279 jbyteArray array;
157 jbyte *bufPtr; 280
281 struct ps_prochandle* ph = get_proc_handle(env, this_obj);
282 if (ph->core != NULL) {
283 return readBytesFromCore(env, ph, this_obj, addr, numBytes);
284 }
158 285
159 array = (*env)->NewByteArray(env, numBytes); 286 array = (*env)->NewByteArray(env, numBytes);
160 CHECK_EXCEPTION_(0); 287 CHECK_EXCEPTION_(0);
161 288
162 unsigned long alignedAddress; 289 unsigned long alignedAddress;
187 &pages[i], &byteCount); 314 &pages[i], &byteCount);
188 mapped[i] = (result == KERN_SUCCESS); 315 mapped[i] = (result == KERN_SUCCESS);
189 // assume all failures are unmapped pages 316 // assume all failures are unmapped pages
190 } 317 }
191 318
192 if (debug) fprintf(stderr, "%ld pages\n", pageCount); 319 print_debug("%ld pages\n", pageCount);
193 320
194 remaining = numBytes; 321 remaining = numBytes;
195 322
196 for (i = 0; i < pageCount; i++) { 323 for (i = 0; i < pageCount; i++) {
197 unsigned long len = vm_page_size; 324 unsigned long len = vm_page_size;
205 if (i == (pageCount - 1)) { 332 if (i == (pageCount - 1)) {
206 len = remaining; 333 len = remaining;
207 } 334 }
208 335
209 if (mapped[i]) { 336 if (mapped[i]) {
210 if (debug) fprintf(stderr, "page %d mapped (len %ld start %ld)\n", i, len, start); 337 print_debug("page %d mapped (len %ld start %ld)\n", i, len, start);
211 (*env)->SetByteArrayRegion(env, array, 0, len, ((jbyte *) pages[i] + start)); 338 (*env)->SetByteArrayRegion(env, array, 0, len, ((jbyte *) pages[i] + start));
212 vm_deallocate(mach_task_self(), pages[i], vm_page_size); 339 vm_deallocate(mach_task_self(), pages[i], vm_page_size);
213 } 340 }
214 341
215 remaining -= len; 342 remaining -= len;
218 free (pages); 345 free (pages);
219 free (mapped); 346 free (mapped);
220 return array; 347 return array;
221 } 348 }
222 349
350 /** Only used for core file reading, set thread_id for threads which is got after core file parsed.
351 * Thread context is available in Mach-O core file but thread id is not. We can get thread id
352 * from Threads which store all java threads information when they are created. Here we can identify
353 * them as java threads by checking if a thread's rsp or rbp within a java thread's stack.
354 * Note Macosx uses unique_thread_id which is different from other platforms though printed ids
355 * are still pthread id. Function BsdDebuggerLocal.getJavaThreadsInfo returns an array of long
356 * integers to host all java threads' id, stack_start, stack_end as:
357 * [uid0, stack_start0, stack_end0, uid1, stack_start1, stack_end1, ...]
358 *
359 * The work cannot be done at init0 since Threads is not available yet(VM not initialized yet).
360 * This function should be called only once if succeeded
361 */
362 bool fill_java_threads(JNIEnv* env, jobject this_obj, struct ps_prochandle* ph) {
363 int n = 0, i = 0, j;
364 struct reg regs;
365
366 jlongArray thrinfos = (*env)->CallObjectMethod(env, this_obj, getJavaThreadsInfo_ID);
367 CHECK_EXCEPTION_(false);
368 int len = (int)(*env)->GetArrayLength(env, thrinfos);
369 uint64_t* cinfos = (uint64_t *)(*env)->GetLongArrayElements(env, thrinfos, NULL);
370 CHECK_EXCEPTION_(false);
371 n = get_num_threads(ph);
372 print_debug("fill_java_threads called, num_of_thread = %d\n", n);
373 for (i = 0; i < n; i++) {
374 if (!get_nth_lwp_regs(ph, i, &regs)) {
375 print_debug("Could not get regs of thread %d, already set!\n", i);
376 return false;
377 }
378 for (j = 0; j < len; j += 3) {
379 lwpid_t uid = cinfos[j];
380 uint64_t beg = cinfos[j + 1];
381 uint64_t end = cinfos[j + 2];
382 if ((regs.r_rsp < end && regs.r_rsp >= beg) ||
383 (regs.r_rbp < end && regs.r_rbp >= beg)) {
384 set_lwp_id(ph, i, uid);
385 break;
386 }
387 }
388 }
389 (*env)->ReleaseLongArrayElements(env, thrinfos, (jlong*)cinfos, 0);
390 CHECK_EXCEPTION_(false);
391 return true;
392 }
393
394 /* For core file only, called from
395 * Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_getThreadIntegerRegisterSet0
396 */
397 jlongArray getThreadIntegerRegisterSetFromCore(JNIEnv *env, jobject this_obj, long lwp_id) {
398 if (!_threads_filled) {
399 if (!fill_java_threads(env, this_obj, get_proc_handle(env, this_obj))) {
400 throw_new_debugger_exception(env, "Failed to fill in threads");
401 return 0;
402 } else {
403 _threads_filled = true;
404 }
405 }
406
407 struct reg gregs;
408 jboolean isCopy;
409 jlongArray array;
410 jlong *regs;
411
412 struct ps_prochandle* ph = get_proc_handle(env, this_obj);
413 if (get_lwp_regs(ph, lwp_id, &gregs) != true) {
414 THROW_NEW_DEBUGGER_EXCEPTION_("get_thread_regs failed for a lwp", 0);
415 }
416
417 #undef NPRGREG
418 #undef REG_INDEX
419 #if amd64
420 #define NPRGREG sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_NPRGREG
421 #define REG_INDEX(reg) sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_##reg
422
423 array = (*env)->NewLongArray(env, NPRGREG);
424 CHECK_EXCEPTION_(0);
425 regs = (*env)->GetLongArrayElements(env, array, &isCopy);
426
427 regs[REG_INDEX(R15)] = gregs.r_r15;
428 regs[REG_INDEX(R14)] = gregs.r_r14;
429 regs[REG_INDEX(R13)] = gregs.r_r13;
430 regs[REG_INDEX(R12)] = gregs.r_r12;
431 regs[REG_INDEX(RBP)] = gregs.r_rbp;
432 regs[REG_INDEX(RBX)] = gregs.r_rbx;
433 regs[REG_INDEX(R11)] = gregs.r_r11;
434 regs[REG_INDEX(R10)] = gregs.r_r10;
435 regs[REG_INDEX(R9)] = gregs.r_r9;
436 regs[REG_INDEX(R8)] = gregs.r_r8;
437 regs[REG_INDEX(RAX)] = gregs.r_rax;
438 regs[REG_INDEX(RCX)] = gregs.r_rcx;
439 regs[REG_INDEX(RDX)] = gregs.r_rdx;
440 regs[REG_INDEX(RSI)] = gregs.r_rsi;
441 regs[REG_INDEX(RDI)] = gregs.r_rdi;
442 regs[REG_INDEX(RIP)] = gregs.r_rip;
443 regs[REG_INDEX(CS)] = gregs.r_cs;
444 regs[REG_INDEX(RSP)] = gregs.r_rsp;
445 regs[REG_INDEX(SS)] = gregs.r_ss;
446 regs[REG_INDEX(FSBASE)] = 0;
447 regs[REG_INDEX(GSBASE)] = 0;
448 regs[REG_INDEX(DS)] = gregs.r_ds;
449 regs[REG_INDEX(ES)] = gregs.r_es;
450 regs[REG_INDEX(FS)] = gregs.r_fs;
451 regs[REG_INDEX(GS)] = gregs.r_gs;
452 regs[REG_INDEX(TRAPNO)] = gregs.r_trapno;
453 regs[REG_INDEX(RFL)] = gregs.r_rflags;
454
455 #endif /* amd64 */
456 (*env)->ReleaseLongArrayElements(env, array, regs, JNI_COMMIT);
457 return array;
458 }
223 459
224 /* 460 /*
225 * Lookup the thread_t that corresponds to the given thread_id. 461 * Lookup the thread_t that corresponds to the given thread_id.
226 * The thread_id should be the result from calling thread_info() with THREAD_IDENTIFIER_INFO 462 * The thread_id should be the result from calling thread_info() with THREAD_IDENTIFIER_INFO
227 * and reading the m_ident_info.thread_id returned. 463 * and reading the m_ident_info.thread_id returned.
230 * We cannot simply use the OSThread._thread_id field in the JVM. This is set to ::mach_thread_self() 466 * We cannot simply use the OSThread._thread_id field in the JVM. This is set to ::mach_thread_self()
231 * in the VM, but that thread port is not valid for a remote debugger to access the thread. 467 * in the VM, but that thread port is not valid for a remote debugger to access the thread.
232 */ 468 */
233 thread_t 469 thread_t
234 lookupThreadFromThreadId(task_t task, jlong thread_id) { 470 lookupThreadFromThreadId(task_t task, jlong thread_id) {
235 if (debug) { 471 print_debug("lookupThreadFromThreadId thread_id=0x%llx\n", thread_id);
236 printf("lookupThreadFromThreadId thread_id=0x%llx\n", thread_id);
237 }
238 472
239 thread_array_t thread_list = NULL; 473 thread_array_t thread_list = NULL;
240 mach_msg_type_number_t thread_list_count = 0; 474 mach_msg_type_number_t thread_list_count = 0;
241 thread_t result_thread = 0; 475 thread_t result_thread = 0;
242 int i; 476 int i;
243 477
244 // get the list of all the send rights 478 // get the list of all the send rights
245 kern_return_t result = task_threads(task, &thread_list, &thread_list_count); 479 kern_return_t result = task_threads(task, &thread_list, &thread_list_count);
246 if (result != KERN_SUCCESS) { 480 if (result != KERN_SUCCESS) {
247 if (debug) { 481 print_debug("task_threads returned 0x%x\n", result);
248 printf("task_threads returned 0x%x\n", result);
249 }
250 return 0; 482 return 0;
251 } 483 }
252 484
253 for(i = 0 ; i < thread_list_count; i++) { 485 for(i = 0 ; i < thread_list_count; i++) {
254 thread_identifier_info_data_t m_ident_info; 486 thread_identifier_info_data_t m_ident_info;
255 mach_msg_type_number_t count = THREAD_IDENTIFIER_INFO_COUNT; 487 mach_msg_type_number_t count = THREAD_IDENTIFIER_INFO_COUNT;
256 488
257 // get the THREAD_IDENTIFIER_INFO for the send right 489 // get the THREAD_IDENTIFIER_INFO for the send right
258 result = thread_info(thread_list[i], THREAD_IDENTIFIER_INFO, (thread_info_t) &m_ident_info, &count); 490 result = thread_info(thread_list[i], THREAD_IDENTIFIER_INFO, (thread_info_t) &m_ident_info, &count);
259 if (result != KERN_SUCCESS) { 491 if (result != KERN_SUCCESS) {
260 if (debug) { 492 print_debug("thread_info returned 0x%x\n", result);
261 printf("thread_info returned 0x%x\n", result);
262 }
263 break; 493 break;
264 } 494 }
265 495
266 // if this is the one we're looking for, return the send right 496 // if this is the one we're looking for, return the send right
267 if (thread_id == m_ident_info.thread_id) 497 if (thread_id == m_ident_info.thread_id)
286 JNIEXPORT jlongArray JNICALL 516 JNIEXPORT jlongArray JNICALL
287 Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_getThreadIntegerRegisterSet0( 517 Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_getThreadIntegerRegisterSet0(
288 JNIEnv *env, jobject this_obj, 518 JNIEnv *env, jobject this_obj,
289 jlong thread_id) 519 jlong thread_id)
290 { 520 {
291 if (debug) 521 print_debug("getThreadRegisterSet0 called\n");
292 printf("getThreadRegisterSet0 called\n"); 522
523 struct ps_prochandle* ph = get_proc_handle(env, this_obj);
524 if (ph->core != NULL) {
525 return getThreadIntegerRegisterSetFromCore(env, this_obj, thread_id);
526 }
293 527
294 kern_return_t result; 528 kern_return_t result;
295 thread_t tid; 529 thread_t tid;
296 mach_msg_type_number_t count = HSDB_THREAD_STATE_COUNT; 530 mach_msg_type_number_t count = HSDB_THREAD_STATE_COUNT;
297 hsdb_thread_state_t state; 531 hsdb_thread_state_t state;
298 unsigned int *r;
299 int i;
300 jlongArray registerArray; 532 jlongArray registerArray;
301 jlong *primitiveArray; 533 jlong *primitiveArray;
302 task_t gTask = getTask(env, this_obj); 534 task_t gTask = getTask(env, this_obj);
303 535
304 tid = lookupThreadFromThreadId(gTask, thread_id); 536 tid = lookupThreadFromThreadId(gTask, thread_id);
305 537
306 result = thread_get_state(tid, HSDB_THREAD_STATE, (thread_state_t)&state, &count); 538 result = thread_get_state(tid, HSDB_THREAD_STATE, (thread_state_t)&state, &count);
307 539
308 if (result != KERN_SUCCESS) { 540 if (result != KERN_SUCCESS) {
309 if (debug) 541 print_error("getregs: thread_get_state(%d) failed (%d)\n", tid, result);
310 printf("getregs: thread_get_state(%d) failed (%d)\n", tid, result);
311 return NULL; 542 return NULL;
312 } 543 }
313 544
314 // 40 32-bit registers on ppc, 16 on x86. 545 #if amd64
315 // Output order is the same as the order in the ppc_thread_state/i386_thread_state struct. 546 #define NPRGREG sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_NPRGREG
316 #if defined(__i386__) 547 #undef REG_INDEX
317 r = (unsigned int *)&state; 548 #define REG_INDEX(reg) sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_##reg
318 registerArray = (*env)->NewLongArray(env, 8); 549
319 primitiveArray = (*env)->GetLongArrayElements(env, registerArray, NULL); 550 // 64 bit
320 primitiveArray[0] = r[0]; // eax 551 print_debug("Getting threads for a 64-bit process\n");
321 primitiveArray[1] = r[2]; // ecx 552 registerArray = (*env)->NewLongArray(env, NPRGREG);
322 primitiveArray[2] = r[3]; // edx 553 CHECK_EXCEPTION_(0);
323 primitiveArray[3] = r[1]; // ebx 554 primitiveArray = (*env)->GetLongArrayElements(env, registerArray, NULL);
324 primitiveArray[4] = r[7]; // esp 555
325 primitiveArray[5] = r[6]; // ebp 556 primitiveArray[REG_INDEX(R15)] = state.__r15;
326 primitiveArray[6] = r[5]; // esi 557 primitiveArray[REG_INDEX(R14)] = state.__r14;
327 primitiveArray[7] = r[4]; // edi 558 primitiveArray[REG_INDEX(R13)] = state.__r13;
328 (*env)->ReleaseLongArrayElements(env, registerArray, primitiveArray, 0); 559 primitiveArray[REG_INDEX(R12)] = state.__r12;
329 #elif defined(__x86_64__) 560 primitiveArray[REG_INDEX(R11)] = state.__r11;
330 /* From AMD64ThreadContext.java 561 primitiveArray[REG_INDEX(R10)] = state.__r10;
331 public static final int R15 = 0; 562 primitiveArray[REG_INDEX(R9)] = state.__r9;
332 public static final int R14 = 1; 563 primitiveArray[REG_INDEX(R8)] = state.__r8;
333 public static final int R13 = 2; 564 primitiveArray[REG_INDEX(RDI)] = state.__rdi;
334 public static final int R12 = 3; 565 primitiveArray[REG_INDEX(RSI)] = state.__rsi;
335 public static final int R11 = 4; 566 primitiveArray[REG_INDEX(RBP)] = state.__rbp;
336 public static final int R10 = 5; 567 primitiveArray[REG_INDEX(RBX)] = state.__rbx;
337 public static final int R9 = 6; 568 primitiveArray[REG_INDEX(RDX)] = state.__rdx;
338 public static final int R8 = 7; 569 primitiveArray[REG_INDEX(RCX)] = state.__rcx;
339 public static final int RDI = 8; 570 primitiveArray[REG_INDEX(RAX)] = state.__rax;
340 public static final int RSI = 9; 571 primitiveArray[REG_INDEX(TRAPNO)] = 0; // trapno, not used
341 public static final int RBP = 10; 572 primitiveArray[REG_INDEX(ERR)] = 0; // err, not used
342 public static final int RBX = 11; 573 primitiveArray[REG_INDEX(RIP)] = state.__rip;
343 public static final int RDX = 12; 574 primitiveArray[REG_INDEX(CS)] = state.__cs;
344 public static final int RCX = 13; 575 primitiveArray[REG_INDEX(RFL)] = state.__rflags;
345 public static final int RAX = 14; 576 primitiveArray[REG_INDEX(RSP)] = state.__rsp;
346 public static final int TRAPNO = 15; 577 primitiveArray[REG_INDEX(SS)] = 0; // We don't have SS
347 public static final int ERR = 16; 578 primitiveArray[REG_INDEX(FS)] = state.__fs;
348 public static final int RIP = 17; 579 primitiveArray[REG_INDEX(GS)] = state.__gs;
349 public static final int CS = 18; 580 primitiveArray[REG_INDEX(ES)] = 0;
350 public static final int RFL = 19; 581 primitiveArray[REG_INDEX(DS)] = 0;
351 public static final int RSP = 20; 582 primitiveArray[REG_INDEX(FSBASE)] = 0;
352 public static final int SS = 21; 583 primitiveArray[REG_INDEX(GSBASE)] = 0;
353 public static final int FS = 22; 584 print_debug("set registers\n");
354 public static final int GS = 23; 585
355 public static final int ES = 24; 586 (*env)->ReleaseLongArrayElements(env, registerArray, primitiveArray, 0);
356 public static final int DS = 25; 587
357 public static final int FSBASE = 26;
358 public static final int GSBASE = 27;
359 */
360 // 64 bit
361 if (debug) printf("Getting threads for a 64-bit process\n");
362 registerArray = (*env)->NewLongArray(env, 28);
363 primitiveArray = (*env)->GetLongArrayElements(env, registerArray, NULL);
364
365 primitiveArray[0] = state.__r15;
366 primitiveArray[1] = state.__r14;
367 primitiveArray[2] = state.__r13;
368 primitiveArray[3] = state.__r12;
369 primitiveArray[4] = state.__r11;
370 primitiveArray[5] = state.__r10;
371 primitiveArray[6] = state.__r9;
372 primitiveArray[7] = state.__r8;
373 primitiveArray[8] = state.__rdi;
374 primitiveArray[9] = state.__rsi;
375 primitiveArray[10] = state.__rbp;
376 primitiveArray[11] = state.__rbx;
377 primitiveArray[12] = state.__rdx;
378 primitiveArray[13] = state.__rcx;
379 primitiveArray[14] = state.__rax;
380 primitiveArray[15] = 0; // trapno ?
381 primitiveArray[16] = 0; // err ?
382 primitiveArray[17] = state.__rip;
383 primitiveArray[18] = state.__cs;
384 primitiveArray[19] = state.__rflags;
385 primitiveArray[20] = state.__rsp;
386 primitiveArray[21] = 0; // We don't have SS
387 primitiveArray[22] = state.__fs;
388 primitiveArray[23] = state.__gs;
389 primitiveArray[24] = 0;
390 primitiveArray[25] = 0;
391 primitiveArray[26] = 0;
392 primitiveArray[27] = 0;
393
394 if (debug) printf("set registers\n");
395
396 (*env)->ReleaseLongArrayElements(env, registerArray, primitiveArray, 0);
397 #else 588 #else
398 #error Unsupported architecture 589 #error UNSUPPORTED_ARCH
399 #endif 590 #endif /* amd64 */
400 591
401 return registerArray; 592 return registerArray;
402 } 593 }
403 594
404 /* 595 /*
408 */ 599 */
409 JNIEXPORT jint JNICALL 600 JNIEXPORT jint JNICALL
410 Java_sun_jvm_hotspot_debugger_macosx_MacOSXDebuggerLocal_translateTID0( 601 Java_sun_jvm_hotspot_debugger_macosx_MacOSXDebuggerLocal_translateTID0(
411 JNIEnv *env, jobject this_obj, jint tid) 602 JNIEnv *env, jobject this_obj, jint tid)
412 { 603 {
413 if (debug) 604 print_debug("translateTID0 called on tid = 0x%x\n", (int)tid);
414 printf("translateTID0 called on tid = 0x%x\n", (int)tid);
415 605
416 kern_return_t result; 606 kern_return_t result;
417 thread_t foreign_tid, usable_tid; 607 thread_t foreign_tid, usable_tid;
418 mach_msg_type_name_t type; 608 mach_msg_type_name_t type;
419 609
424 MACH_MSG_TYPE_COPY_SEND, 614 MACH_MSG_TYPE_COPY_SEND,
425 &usable_tid, &type); 615 &usable_tid, &type);
426 if (result != KERN_SUCCESS) 616 if (result != KERN_SUCCESS)
427 return -1; 617 return -1;
428 618
429 if (debug) 619 print_debug("translateTID0: 0x%x -> 0x%x\n", foreign_tid, usable_tid);
430 printf("translateTID0: 0x%x -> 0x%x\n", foreign_tid, usable_tid);
431 620
432 return (jint) usable_tid; 621 return (jint) usable_tid;
433 } 622 }
434 623
435 624
436 static bool ptrace_continue(pid_t pid, int signal) { 625 static bool ptrace_continue(pid_t pid, int signal) {
437 // pass the signal to the process so we don't swallow it 626 // pass the signal to the process so we don't swallow it
438 int res; 627 int res;
439 if ((res = ptrace(PT_CONTINUE, pid, (caddr_t)1, signal)) < 0) { 628 if ((res = ptrace(PT_CONTINUE, pid, (caddr_t)1, signal)) < 0) {
440 fprintf(stderr, "attach: ptrace(PT_CONTINUE, %d) failed with %d\n", pid, res); 629 print_error("attach: ptrace(PT_CONTINUE, %d) failed with %d\n", pid, res);
441 return false; 630 return false;
442 } 631 }
443 return true; 632 return true;
444 } 633 }
445 634
459 if (WSTOPSIG(status) == SIGSTOP) { 648 if (WSTOPSIG(status) == SIGSTOP) {
460 // Debuggee stopped by SIGSTOP. 649 // Debuggee stopped by SIGSTOP.
461 return true; 650 return true;
462 } 651 }
463 if (!ptrace_continue(pid, WSTOPSIG(status))) { 652 if (!ptrace_continue(pid, WSTOPSIG(status))) {
464 fprintf(stderr, "attach: Failed to correctly attach to VM. VM might HANG! [PTRACE_CONT failed, stopped by %d]\n", WSTOPSIG(status)); 653 print_error("attach: Failed to correctly attach to VM. VM might HANG! [PTRACE_CONT failed, stopped by %d]\n", WSTOPSIG(status));
465 return false; 654 return false;
466 } 655 }
467 } else { 656 } else {
468 fprintf(stderr, "attach: waitpid(): Child process exited/terminated (status = 0x%x)\n", status); 657 print_error("attach: waitpid(): Child process exited/terminated (status = 0x%x)\n", status);
469 return false; 658 return false;
470 } 659 }
471 } else { 660 } else {
472 switch (errno) { 661 switch (errno) {
473 case EINTR: 662 case EINTR:
474 continue; 663 continue;
475 break; 664 break;
476 case ECHILD: 665 case ECHILD:
477 fprintf(stderr, "attach: waitpid() failed. Child process pid (%d) does not exist \n", pid); 666 print_error("attach: waitpid() failed. Child process pid (%d) does not exist \n", pid);
478 break; 667 break;
479 case EINVAL: 668 case EINVAL:
480 fprintf(stderr, "attach: waitpid() failed. Invalid options argument.\n"); 669 print_error("attach: waitpid() failed. Invalid options argument.\n");
481 break; 670 break;
482 default: 671 default:
483 fprintf(stderr, "attach: waitpid() failed. Unexpected error %d\n",errno); 672 print_error("attach: waitpid() failed. Unexpected error %d\n",errno);
484 break; 673 break;
485 } 674 }
486 return false; 675 return false;
487 } 676 }
488 } 677 }
490 679
491 // attach to a process/thread specified by "pid" 680 // attach to a process/thread specified by "pid"
492 static bool ptrace_attach(pid_t pid) { 681 static bool ptrace_attach(pid_t pid) {
493 int res; 682 int res;
494 if ((res = ptrace(PT_ATTACH, pid, 0, 0)) < 0) { 683 if ((res = ptrace(PT_ATTACH, pid, 0, 0)) < 0) {
495 fprintf(stderr, "ptrace(PT_ATTACH, %d) failed with %d\n", pid, res); 684 print_error("ptrace(PT_ATTACH, %d) failed with %d\n", pid, res);
496 return false; 685 return false;
497 } else { 686 } else {
498 return ptrace_waitpid(pid); 687 return ptrace_waitpid(pid);
499 } 688 }
500 } 689 }
502 /* 691 /*
503 * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal 692 * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
504 * Method: attach0 693 * Method: attach0
505 * Signature: (I)V 694 * Signature: (I)V
506 */ 695 */
507 JNIEXPORT void JNICALL 696 JNIEXPORT void JNICALL
508 Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_attach0__I( 697 Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_attach0__I(
509 JNIEnv *env, jobject this_obj, jint jpid) 698 JNIEnv *env, jobject this_obj, jint jpid)
510 { 699 {
700 print_debug("attach0 called for jpid=%d\n", (int)jpid);
701
511 JNF_COCOA_ENTER(env); 702 JNF_COCOA_ENTER(env);
512 if (getenv("JAVA_SAPROC_DEBUG") != NULL) 703
513 debug = JNI_TRUE;
514 else
515 debug = JNI_FALSE;
516 if (debug) printf("attach0 called for jpid=%d\n", (int)jpid);
517
518 // get the task from the pid
519 kern_return_t result; 704 kern_return_t result;
520 task_t gTask = 0; 705 task_t gTask = 0;
521 result = task_for_pid(mach_task_self(), jpid, &gTask); 706 result = task_for_pid(mach_task_self(), jpid, &gTask);
522 if (result != KERN_SUCCESS) { 707 if (result != KERN_SUCCESS) {
523 fprintf(stderr, "attach: task_for_pid(%d) failed (%d)\n", (int)jpid, result); 708 print_error("attach: task_for_pid(%d) failed (%d)\n", (int)jpid, result);
524 THROW_NEW_DEBUGGER_EXCEPTION("Can't attach to the process"); 709 THROW_NEW_DEBUGGER_EXCEPTION("Can't attach to the process");
525 } 710 }
526 putTask(env, this_obj, gTask); 711 putTask(env, this_obj, gTask);
527 712
528 // use ptrace to stop the process 713 // use ptrace to stop the process
548 } 733 }
549 734
550 JNF_COCOA_EXIT(env); 735 JNF_COCOA_EXIT(env);
551 } 736 }
552 737
738 /** For core file,
739 called from Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_attach0__Ljava_lang_String_2Ljava_lang_String_2 */
740 static void fillLoadObjects(JNIEnv* env, jobject this_obj, struct ps_prochandle* ph) {
741 int n = 0, i = 0;
742
743 // add load objects
744 n = get_num_libs(ph);
745 for (i = 0; i < n; i++) {
746 uintptr_t base;
747 const char* name;
748 jobject loadObject;
749 jobject loadObjectList;
750
751 base = get_lib_base(ph, i);
752 name = get_lib_name(ph, i);
753 loadObject = (*env)->CallObjectMethod(env, this_obj, createLoadObject_ID,
754 (*env)->NewStringUTF(env, name), (jlong)0, (jlong)base);
755 CHECK_EXCEPTION;
756 loadObjectList = (*env)->GetObjectField(env, this_obj, loadObjectList_ID);
757 CHECK_EXCEPTION;
758 (*env)->CallBooleanMethod(env, loadObjectList, listAdd_ID, loadObject);
759 CHECK_EXCEPTION;
760 }
761 }
762
763 /*
764 * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
765 * Method: attach0
766 * Signature: (Ljava/lang/String;Ljava/lang/String;)V
767 */
768 JNIEXPORT void JNICALL
769 Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_attach0__Ljava_lang_String_2Ljava_lang_String_2(
770 JNIEnv *env, jobject this_obj, jstring execName, jstring coreName)
771 {
772 const char *execName_cstr;
773 const char *coreName_cstr;
774 jboolean isCopy;
775 struct ps_prochandle* ph;
776
777 execName_cstr = (*env)->GetStringUTFChars(env, execName, &isCopy);
778 CHECK_EXCEPTION;
779 coreName_cstr = (*env)->GetStringUTFChars(env, coreName, &isCopy);
780 CHECK_EXCEPTION;
781
782 print_debug("attach: %s %s\n", execName_cstr, coreName_cstr);
783
784 if ( (ph = Pgrab_core(execName_cstr, coreName_cstr)) == NULL) {
785 (*env)->ReleaseStringUTFChars(env, execName, execName_cstr);
786 (*env)->ReleaseStringUTFChars(env, coreName, coreName_cstr);
787 THROW_NEW_DEBUGGER_EXCEPTION("Can't attach to the core file");
788 }
789 (*env)->SetLongField(env, this_obj, p_ps_prochandle_ID, (jlong)(intptr_t)ph);
790 (*env)->ReleaseStringUTFChars(env, execName, execName_cstr);
791 (*env)->ReleaseStringUTFChars(env, coreName, coreName_cstr);
792 fillLoadObjects(env, this_obj, ph);
793 }
794
553 /* 795 /*
554 * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal 796 * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
555 * Method: detach0 797 * Method: detach0
556 * Signature: ()V 798 * Signature: ()V
557 */ 799 */
558 JNIEXPORT void JNICALL 800 JNIEXPORT void JNICALL
559 Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_detach0( 801 Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_detach0(
560 JNIEnv *env, jobject this_obj) 802 JNIEnv *env, jobject this_obj)
561 { 803 {
804 print_debug("detach0 called\n");
805 struct ps_prochandle* ph = get_proc_handle(env, this_obj);
806 if (ph != NULL && ph->core != NULL) {
807 Prelease(ph);
808 return;
809 }
562 JNF_COCOA_ENTER(env); 810 JNF_COCOA_ENTER(env);
563 if (debug) printf("detach0 called\n");
564
565 task_t gTask = getTask(env, this_obj); 811 task_t gTask = getTask(env, this_obj);
566 812
567 // detach from the ptraced process causing it to resume execution 813 // detach from the ptraced process causing it to resume execution
568 int pid; 814 int pid;
569 kern_return_t k_res; 815 kern_return_t k_res;
570 k_res = pid_for_task(gTask, &pid); 816 k_res = pid_for_task(gTask, &pid);
571 if (k_res != KERN_SUCCESS) { 817 if (k_res != KERN_SUCCESS) {
572 fprintf(stderr, "detach: pid_for_task(%d) failed (%d)\n", pid, k_res); 818 print_error("detach: pid_for_task(%d) failed (%d)\n", pid, k_res);
573 } 819 }
574 else { 820 else {
575 int res = ptrace(PT_DETACH, pid, 0, 0); 821 int res = ptrace(PT_DETACH, pid, 0, 0);
576 if (res < 0) { 822 if (res < 0) {
577 fprintf(stderr, "detach: ptrace(PT_DETACH, %d) failed (%d)\n", pid, res); 823 print_error("detach: ptrace(PT_DETACH, %d) failed (%d)\n", pid, res);
578 } 824 }
579 } 825 }
580 826
581 mach_port_deallocate(mach_task_self(), gTask); 827 mach_port_deallocate(mach_task_self(), gTask);
582 id symbolicator = getSymbolicator(env, this_obj); 828 id symbolicator = getSymbolicator(env, this_obj);
583 if (symbolicator != nil) { 829 if (symbolicator != nil) {
584 CFRelease(symbolicator); 830 CFRelease(symbolicator);
585 } 831 }
586 JNF_COCOA_EXIT(env); 832 JNF_COCOA_EXIT(env);
587 } 833 }
588
589 /*
590 * Class: sun_jvm_hotspot_asm_Disassembler
591 * Method: load_library
592 * Signature: (Ljava/lang/String;)L
593 */
594 JNIEXPORT jlong JNICALL
595 Java_sun_jvm_hotspot_asm_Disassembler_load_1library(
596 JNIEnv * env,
597 jclass disclass,
598 jstring jrepath_s,
599 jstring libname_s)
600 {
601 uintptr_t func = 0;
602 const char* error_message = NULL;
603 const char* java_home;
604 jboolean isCopy;
605 uintptr_t *handle = NULL;
606
607 const char * jrepath = (*env)->GetStringUTFChars(env, jrepath_s, &isCopy); // like $JAVA_HOME/jre/lib/sparc/
608 const char * libname = (*env)->GetStringUTFChars(env, libname_s, &isCopy);
609 char buffer[128];
610
611 /* Load the hsdis library */
612 void* hsdis_handle;
613 hsdis_handle = dlopen(libname, RTLD_LAZY | RTLD_GLOBAL);
614 if (hsdis_handle == NULL) {
615 snprintf(buffer, sizeof(buffer), "%s%s", jrepath, libname);
616 hsdis_handle = dlopen(buffer, RTLD_LAZY | RTLD_GLOBAL);
617 }
618 if (hsdis_handle != NULL) {
619 func = (uintptr_t)dlsym(hsdis_handle, "decode_instructions_virtual");
620 }
621 if (func == 0) {
622 error_message = dlerror();
623 fprintf(stderr, "%s\n", error_message);
624 }
625
626 (*env)->ReleaseStringUTFChars(env, libname_s, libname);
627 (*env)->ReleaseStringUTFChars(env, jrepath_s, jrepath);
628
629 if (func == 0) {
630 /* Couldn't find entry point. error_message should contain some
631 * platform dependent error message.
632 */
633 THROW_NEW_DEBUGGER_EXCEPTION_(error_message, (jlong)func);
634 }
635 return (jlong)func;
636 }
637
638 /* signature of decode_instructions_virtual from hsdis.h */
639 typedef void* (*decode_func)(uintptr_t start_va, uintptr_t end_va,
640 unsigned char* start, uintptr_t length,
641 void* (*event_callback)(void*, const char*, void*),
642 void* event_stream,
643 int (*printf_callback)(void*, const char*, ...),
644 void* printf_stream,
645 const char* options);
646
647 /* container for call back state when decoding instructions */
648 typedef struct {
649 JNIEnv* env;
650 jobject dis;
651 jobject visitor;
652 jmethodID handle_event;
653 jmethodID raw_print;
654 char buffer[4096];
655 } decode_env;
656
657
658 /* event callback binding to Disassembler.handleEvent */
659 static void* event_to_env(void* env_pv, const char* event, void* arg) {
660 decode_env* denv = (decode_env*)env_pv;
661 JNIEnv* env = denv->env;
662 jstring event_string = (*env)->NewStringUTF(env, event);
663 jlong result = (*env)->CallLongMethod(env, denv->dis, denv->handle_event, denv->visitor,
664 event_string, (jlong) (uintptr_t)arg);
665 /* ignore exceptions for now */
666 CHECK_EXCEPTION_CLEAR_((void *)0);
667 return (void*)(uintptr_t)result;
668 }
669
670 /* printing callback binding to Disassembler.rawPrint */
671 static int printf_to_env(void* env_pv, const char* format, ...) {
672 jstring output;
673 va_list ap;
674 int cnt;
675 decode_env* denv = (decode_env*)env_pv;
676 JNIEnv* env = denv->env;
677 size_t flen = strlen(format);
678 const char* raw = NULL;
679
680 if (flen == 0) return 0;
681 if (flen < 2 ||
682 strchr(format, '%') == NULL) {
683 raw = format;
684 } else if (format[0] == '%' && format[1] == '%' &&
685 strchr(format+2, '%') == NULL) {
686 // happens a lot on machines with names like %foo
687 flen--;
688 raw = format+1;
689 }
690 if (raw != NULL) {
691 jstring output = (*env)->NewStringUTF(env, raw);
692 (*env)->CallVoidMethod(env, denv->dis, denv->raw_print, denv->visitor, output);
693 CHECK_EXCEPTION_CLEAR;
694 return (int) flen;
695 }
696 va_start(ap, format);
697 cnt = vsnprintf(denv->buffer, sizeof(denv->buffer), format, ap);
698 va_end(ap);
699
700 output = (*env)->NewStringUTF(env, denv->buffer);
701 (*env)->CallVoidMethod(env, denv->dis, denv->raw_print, denv->visitor, output);
702 CHECK_EXCEPTION_CLEAR;
703 return cnt;
704 }
705
706 /*
707 * Class: sun_jvm_hotspot_asm_Disassembler
708 * Method: decode
709 * Signature: (Lsun/jvm/hotspot/asm/InstructionVisitor;J[BLjava/lang/String;J)V
710 */
711 JNIEXPORT void JNICALL
712 Java_sun_jvm_hotspot_asm_Disassembler_decode(
713 JNIEnv * env,
714 jobject dis,
715 jobject visitor,
716 jlong startPc,
717 jbyteArray code,
718 jstring options_s,
719 jlong decode_instructions_virtual)
720 {
721 jboolean isCopy;
722 jbyte* start = (*env)->GetByteArrayElements(env, code, &isCopy);
723 jbyte* end = start + (*env)->GetArrayLength(env, code);
724 const char * options = (*env)->GetStringUTFChars(env, options_s, &isCopy);
725 jclass disclass = (*env)->GetObjectClass(env, dis);
726
727 decode_env denv;
728 denv.env = env;
729 denv.dis = dis;
730 denv.visitor = visitor;
731
732 /* find Disassembler.handleEvent callback */
733 denv.handle_event = (*env)->GetMethodID(env, disclass, "handleEvent",
734 "(Lsun/jvm/hotspot/asm/InstructionVisitor;Ljava/lang/String;J)J");
735 CHECK_EXCEPTION_CLEAR_VOID
736
737 /* find Disassembler.rawPrint callback */
738 denv.raw_print = (*env)->GetMethodID(env, disclass, "rawPrint",
739 "(Lsun/jvm/hotspot/asm/InstructionVisitor;Ljava/lang/String;)V");
740 CHECK_EXCEPTION_CLEAR_VOID
741
742 /* decode the buffer */
743 (*(decode_func)(uintptr_t)decode_instructions_virtual)(startPc,
744 startPc + end - start,
745 (unsigned char*)start,
746 end - start,
747 &event_to_env, (void*) &denv,
748 &printf_to_env, (void*) &denv,
749 options);
750
751 /* cleanup */
752 (*env)->ReleaseByteArrayElements(env, code, start, JNI_ABORT);
753 (*env)->ReleaseStringUTFChars(env, options_s, options);
754 }