1 /* 2 * Copyright (c) 2002, 2018, 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 <objc/objc-runtime.h> 26 #import <Foundation/Foundation.h> 27 #import <JavaNativeFoundation/JavaNativeFoundation.h> 28 #import <JavaRuntimeSupport/JavaRuntimeSupport.h> 29 30 #include <jni.h> 31 32 #import <mach/mach.h> 33 #import <mach/mach_types.h> 34 #import <sys/sysctl.h> 35 #import <stdio.h> 36 #import <string.h> 37 #import <stdarg.h> 38 #import <stdlib.h> 39 #import <strings.h> 40 #import <dlfcn.h> 41 #import <limits.h> 42 #import <errno.h> 43 #import <sys/types.h> 44 #import <sys/ptrace.h> 45 #include "libproc_impl.h" 46 47 #define UNSUPPORTED_ARCH "Unsupported architecture!" 48 49 #if defined(x86_64) && !defined(amd64) 50 #define amd64 1 51 #endif 52 53 #if amd64 54 #include "sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext.h" 55 #else 56 #error UNSUPPORTED_ARCH 57 #endif 58 59 static jfieldID symbolicatorID = 0; // set in _init0 60 static jfieldID taskID = 0; // set in _init0 61 62 static jfieldID p_ps_prochandle_ID = 0; 63 static jfieldID loadObjectList_ID = 0; 64 static jmethodID listAdd_ID = 0; 65 66 static jmethodID createClosestSymbol_ID = 0; 67 static jmethodID createLoadObject_ID = 0; 68 static jmethodID getJavaThreadsInfo_ID = 0; 69 70 // indicator if thread id (lwpid_t) was set 71 static bool _threads_filled = false; 72 73 // mach_exc_server defined in the generated mach_excServer.c 74 extern boolean_t mach_exc_server(mach_msg_header_t *input_msg_hdr, 75 mach_msg_header_t *output_msg_hdr); 76 77 kern_return_t catch_mach_exception_raise( 78 mach_port_t exception_port, mach_port_t thread, 79 mach_port_t task, exception_type_t exception, 80 mach_exception_data_t code, 81 mach_msg_type_number_t code_cnt); 82 83 kern_return_t catch_mach_exception_raise_state( 84 mach_port_t exception_port, exception_type_t exception, 85 const mach_exception_data_t code, mach_msg_type_number_t code_cnt, 86 int *flavor, const thread_state_t old_state, 87 mach_msg_type_number_t old_state_cnt, thread_state_t new_state, 88 mach_msg_type_number_t *new_state_cnt); 89 90 kern_return_t catch_mach_exception_raise_state_identity( 91 mach_port_t exception_port, mach_port_t thread, mach_port_t task, 92 exception_type_t exception, mach_exception_data_t code, 93 mach_msg_type_number_t code_cnt, int *flavor, thread_state_t old_state, 94 mach_msg_type_number_t old_state_cnt, thread_state_t new_state, 95 mach_msg_type_number_t *new_state_cnt); 96 97 static struct exception_saved_state { 98 exception_mask_t saved_masks[EXC_TYPES_COUNT]; 99 mach_port_t saved_ports[EXC_TYPES_COUNT]; 100 exception_behavior_t saved_behaviors[EXC_TYPES_COUNT]; 101 thread_state_flavor_t saved_flavors[EXC_TYPES_COUNT]; 102 mach_msg_type_number_t saved_exception_types_count; 103 } exception_saved_state; 104 105 static mach_port_t tgt_exception_port; 106 107 // Mirrors __Reply__mach_exception_raise_t generated in mach_excServer.c 108 static struct rep_msg { 109 mach_msg_header_t header; 110 NDR_record_t ndr; 111 kern_return_t ret_code; 112 } rep_msg; 113 114 // Mirrors __Request__mach_exception_raise_t generated in mach_excServer.c 115 // with a large trailing pad to avoid MACH_MSG_RCV_TOO_LARGE 116 static struct exc_msg { 117 mach_msg_header_t header; 118 // start of the kernel processed data 119 mach_msg_body_t msgh_body; 120 mach_msg_port_descriptor_t thread; 121 mach_msg_port_descriptor_t task; 122 // end of the kernel processed data 123 NDR_record_t ndr; 124 exception_type_t exception; 125 mach_msg_type_number_t code_cnt; 126 mach_exception_data_t code; // an array of int64_t 127 char pad[512]; 128 } exc_msg; 129 130 static void putSymbolicator(JNIEnv *env, jobject this_obj, id symbolicator) { 131 (*env)->SetLongField(env, this_obj, symbolicatorID, (jlong)(intptr_t)symbolicator); 132 } 133 134 static id getSymbolicator(JNIEnv *env, jobject this_obj) { 135 jlong ptr = (*env)->GetLongField(env, this_obj, symbolicatorID); 136 return (id)(intptr_t)ptr; 137 } 138 139 static void putTask(JNIEnv *env, jobject this_obj, task_t task) { 140 (*env)->SetLongField(env, this_obj, taskID, (jlong)task); 141 } 142 143 static task_t getTask(JNIEnv *env, jobject this_obj) { 144 jlong ptr = (*env)->GetLongField(env, this_obj, taskID); 145 return (task_t)ptr; 146 } 147 148 #define CHECK_EXCEPTION_(value) if ((*env)->ExceptionOccurred(env)) { return value; } 149 #define CHECK_EXCEPTION if ((*env)->ExceptionOccurred(env)) { return;} 150 #define THROW_NEW_DEBUGGER_EXCEPTION_(str, value) { throw_new_debugger_exception(env, str); return value; } 151 #define THROW_NEW_DEBUGGER_EXCEPTION(str) { throw_new_debugger_exception(env, str); return;} 152 #define CHECK_EXCEPTION_CLEAR if ((*env)->ExceptionOccurred(env)) { (*env)->ExceptionClear(env); } 153 #define CHECK_EXCEPTION_CLEAR_VOID if ((*env)->ExceptionOccurred(env)) { (*env)->ExceptionClear(env); return; } 154 #define CHECK_EXCEPTION_CLEAR_(value) if ((*env)->ExceptionOccurred(env)) { (*env)->ExceptionClear(env); return value; } 155 156 static void throw_new_debugger_exception(JNIEnv* env, const char* errMsg) { 157 jclass exceptionClass = (*env)->FindClass(env, "sun/jvm/hotspot/debugger/DebuggerException"); 158 CHECK_EXCEPTION; 159 (*env)->ThrowNew(env, exceptionClass, errMsg); 160 } 161 162 static struct ps_prochandle* get_proc_handle(JNIEnv* env, jobject this_obj) { 163 jlong ptr = (*env)->GetLongField(env, this_obj, p_ps_prochandle_ID); 164 return (struct ps_prochandle*)(intptr_t)ptr; 165 } 166 167 #if defined(__i386__) 168 #define hsdb_thread_state_t x86_thread_state32_t 169 #define hsdb_float_state_t x86_float_state32_t 170 #define HSDB_THREAD_STATE x86_THREAD_STATE32 171 #define HSDB_FLOAT_STATE x86_FLOAT_STATE32 172 #define HSDB_THREAD_STATE_COUNT x86_THREAD_STATE32_COUNT 173 #define HSDB_FLOAT_STATE_COUNT x86_FLOAT_STATE32_COUNT 174 #elif defined(__x86_64__) 175 #define hsdb_thread_state_t x86_thread_state64_t 176 #define hsdb_float_state_t x86_float_state64_t 177 #define HSDB_THREAD_STATE x86_THREAD_STATE64 178 #define HSDB_FLOAT_STATE x86_FLOAT_STATE64 179 #define HSDB_THREAD_STATE_COUNT x86_THREAD_STATE64_COUNT 180 #define HSDB_FLOAT_STATE_COUNT x86_FLOAT_STATE64_COUNT 181 #else 182 #error UNSUPPORTED_ARCH 183 #endif 184 185 /* 186 * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal 187 * Method: init0 188 * Signature: ()V 189 */ 190 JNIEXPORT void JNICALL 191 Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_init0(JNIEnv *env, jclass cls) { 192 symbolicatorID = (*env)->GetFieldID(env, cls, "symbolicator", "J"); 193 CHECK_EXCEPTION; 194 taskID = (*env)->GetFieldID(env, cls, "task", "J"); 195 CHECK_EXCEPTION; 196 197 // for core file 198 p_ps_prochandle_ID = (*env)->GetFieldID(env, cls, "p_ps_prochandle", "J"); 199 CHECK_EXCEPTION; 200 loadObjectList_ID = (*env)->GetFieldID(env, cls, "loadObjectList", "Ljava/util/List;"); 201 CHECK_EXCEPTION; 202 203 // methods we use 204 createClosestSymbol_ID = (*env)->GetMethodID(env, cls, "createClosestSymbol", 205 "(Ljava/lang/String;J)Lsun/jvm/hotspot/debugger/cdbg/ClosestSymbol;"); 206 CHECK_EXCEPTION; 207 createLoadObject_ID = (*env)->GetMethodID(env, cls, "createLoadObject", 208 "(Ljava/lang/String;JJ)Lsun/jvm/hotspot/debugger/cdbg/LoadObject;"); 209 CHECK_EXCEPTION; 210 211 // java.util.List method we call 212 jclass listClass = (*env)->FindClass(env, "java/util/List"); 213 CHECK_EXCEPTION; 214 listAdd_ID = (*env)->GetMethodID(env, listClass, "add", "(Ljava/lang/Object;)Z"); 215 CHECK_EXCEPTION; 216 getJavaThreadsInfo_ID = (*env)->GetMethodID(env, cls, "getJavaThreadsInfo", 217 "()[J"); 218 CHECK_EXCEPTION; 219 220 init_libproc(getenv("LIBSAPROC_DEBUG") != NULL); 221 } 222 223 JNIEXPORT jint JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_getAddressSize 224 (JNIEnv *env, jclass cls) 225 { 226 #ifdef _LP64 227 return 8; 228 #else 229 #error UNSUPPORTED_ARCH 230 #endif 231 } 232 233 /** called by Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_lookupByName0 */ 234 jlong lookupByNameIncore( 235 JNIEnv *env, struct ps_prochandle *ph, jobject this_obj, jstring objectName, jstring symbolName) 236 { 237 const char *objectName_cstr, *symbolName_cstr; 238 jlong addr; 239 jboolean isCopy; 240 objectName_cstr = NULL; 241 if (objectName != NULL) { 242 objectName_cstr = (*env)->GetStringUTFChars(env, objectName, &isCopy); 243 CHECK_EXCEPTION_(0); 244 } 245 symbolName_cstr = (*env)->GetStringUTFChars(env, symbolName, &isCopy); 246 CHECK_EXCEPTION_(0); 247 248 print_debug("look for %s \n", symbolName_cstr); 249 addr = (jlong) lookup_symbol(ph, objectName_cstr, symbolName_cstr); 250 251 if (objectName_cstr != NULL) { 252 (*env)->ReleaseStringUTFChars(env, objectName, objectName_cstr); 253 } 254 (*env)->ReleaseStringUTFChars(env, symbolName, symbolName_cstr); 255 return addr; 256 } 257 258 /* 259 * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal 260 * Method: lookupByName0 261 * Signature: (Ljava/lang/String;Ljava/lang/String;)J 262 */ 263 JNIEXPORT jlong JNICALL 264 Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_lookupByName0( 265 JNIEnv *env, jobject this_obj, 266 jstring objectName, jstring symbolName) 267 { 268 struct ps_prochandle* ph = get_proc_handle(env, this_obj); 269 if (ph != NULL && ph->core != NULL) { 270 return lookupByNameIncore(env, ph, this_obj, objectName, symbolName); 271 } 272 273 jlong address = 0; 274 275 JNF_COCOA_ENTER(env); 276 NSString *symbolNameString = JNFJavaToNSString(env, symbolName); 277 278 print_debug("lookupInProcess called for %s\n", [symbolNameString UTF8String]); 279 280 id symbolicator = getSymbolicator(env, this_obj); 281 if (symbolicator != nil) { 282 uint64_t (*dynamicCall)(id, SEL, NSString *) = (uint64_t (*)(id, SEL, NSString *))&objc_msgSend; 283 address = (jlong) dynamicCall(symbolicator, @selector(addressForSymbol:), symbolNameString); 284 } 285 286 print_debug("address of symbol %s = %llx\n", [symbolNameString UTF8String], address); 287 JNF_COCOA_EXIT(env); 288 289 return address; 290 } 291 292 /* 293 * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal 294 * Method: lookupByAddress0 295 * Signature: (J)Lsun/jvm/hotspot/debugger/cdbg/ClosestSymbol; 296 */ 297 JNIEXPORT jobject JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_lookupByAddress0 298 (JNIEnv *env, jobject this_obj, jlong addr) { 299 uintptr_t offset; 300 const char* sym = NULL; 301 jstring sym_string; 302 303 struct ps_prochandle* ph = get_proc_handle(env, this_obj); 304 if (ph != NULL && ph->core != NULL) { 305 sym = symbol_for_pc(ph, (uintptr_t) addr, &offset); 306 if (sym == NULL) return 0; 307 sym_string = (*env)->NewStringUTF(env, sym); 308 CHECK_EXCEPTION_(0); 309 return (*env)->CallObjectMethod(env, this_obj, createClosestSymbol_ID, 310 sym_string, (jlong)offset); 311 } 312 return 0; 313 } 314 315 /** called from Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_readBytesFromProcess0 */ 316 jbyteArray readBytesFromCore( 317 JNIEnv *env, struct ps_prochandle *ph, jobject this_obj, jlong addr, jlong numBytes) 318 { 319 jboolean isCopy; 320 jbyteArray array; 321 jbyte *bufPtr; 322 ps_err_e err; 323 324 array = (*env)->NewByteArray(env, numBytes); 325 CHECK_EXCEPTION_(0); 326 bufPtr = (*env)->GetByteArrayElements(env, array, &isCopy); 327 CHECK_EXCEPTION_(0); 328 329 err = ps_pread(ph, (psaddr_t) (uintptr_t)addr, bufPtr, numBytes); 330 (*env)->ReleaseByteArrayElements(env, array, bufPtr, 0); 331 return (err == PS_OK)? array : 0; 332 } 333 334 /* 335 * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal 336 * Method: readBytesFromProcess0 337 * Signature: (JJ)Lsun/jvm/hotspot/debugger/ReadResult; 338 */ 339 JNIEXPORT jbyteArray JNICALL 340 Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_readBytesFromProcess0( 341 JNIEnv *env, jobject this_obj, 342 jlong addr, jlong numBytes) 343 { 344 print_debug("readBytesFromProcess called. addr = %llx numBytes = %lld\n", addr, numBytes); 345 346 // must allocate storage instead of using former parameter buf 347 jbyteArray array; 348 349 struct ps_prochandle* ph = get_proc_handle(env, this_obj); 350 if (ph != NULL && ph->core != NULL) { 351 return readBytesFromCore(env, ph, this_obj, addr, numBytes); 352 } 353 354 array = (*env)->NewByteArray(env, numBytes); 355 CHECK_EXCEPTION_(0); 356 357 unsigned long alignedAddress; 358 unsigned long alignedLength = 0; 359 kern_return_t result; 360 vm_offset_t *pages; 361 int *mapped; 362 long pageCount; 363 uint byteCount; 364 int i; 365 unsigned long remaining; 366 367 alignedAddress = trunc_page(addr); 368 if (addr != alignedAddress) { 369 alignedLength += addr - alignedAddress; 370 } 371 alignedLength = round_page(numBytes); 372 pageCount = alignedLength/vm_page_size; 373 374 // Allocate storage for pages and flags. 375 pages = malloc(pageCount * sizeof(vm_offset_t)); 376 mapped = calloc(pageCount, sizeof(int)); 377 378 task_t gTask = getTask(env, this_obj); 379 // Try to read each of the pages. 380 for (i = 0; i < pageCount; i++) { 381 result = vm_read(gTask, alignedAddress + i*vm_page_size, vm_page_size, 382 &pages[i], &byteCount); 383 mapped[i] = (result == KERN_SUCCESS); 384 // assume all failures are unmapped pages 385 } 386 387 print_debug("%ld pages\n", pageCount); 388 389 remaining = numBytes; 390 391 for (i = 0; i < pageCount; i++) { 392 unsigned long len = vm_page_size; 393 unsigned long start = 0; 394 395 if (i == 0) { 396 start = addr - alignedAddress; 397 len = vm_page_size - start; 398 } 399 400 if (i == (pageCount - 1)) { 401 len = remaining; 402 } 403 404 if (mapped[i]) { 405 print_debug("page %d mapped (len %ld start %ld)\n", i, len, start); 406 (*env)->SetByteArrayRegion(env, array, 0, len, ((jbyte *) pages[i] + start)); 407 vm_deallocate(mach_task_self(), pages[i], vm_page_size); 408 } 409 410 remaining -= len; 411 } 412 413 free (pages); 414 free (mapped); 415 return array; 416 } 417 418 /** Only used for core file reading, set thread_id for threads which is got after core file parsed. 419 * Thread context is available in Mach-O core file but thread id is not. We can get thread id 420 * from Threads which store all java threads information when they are created. Here we can identify 421 * them as java threads by checking if a thread's rsp or rbp within a java thread's stack. 422 * Note Macosx uses unique_thread_id which is different from other platforms though printed ids 423 * are still pthread id. Function BsdDebuggerLocal.getJavaThreadsInfo returns an array of long 424 * integers to host all java threads' id, stack_start, stack_end as: 425 * [uid0, stack_start0, stack_end0, uid1, stack_start1, stack_end1, ...] 426 * 427 * The work cannot be done at init0 since Threads is not available yet(VM not initialized yet). 428 * This function should be called only once if succeeded 429 */ 430 bool fill_java_threads(JNIEnv* env, jobject this_obj, struct ps_prochandle* ph) { 431 int n = 0, i = 0, j; 432 struct reg regs; 433 434 jlongArray thrinfos = (*env)->CallObjectMethod(env, this_obj, getJavaThreadsInfo_ID); 435 CHECK_EXCEPTION_(false); 436 int len = (int)(*env)->GetArrayLength(env, thrinfos); 437 uint64_t* cinfos = (uint64_t *)(*env)->GetLongArrayElements(env, thrinfos, NULL); 438 CHECK_EXCEPTION_(false); 439 n = get_num_threads(ph); 440 print_debug("fill_java_threads called, num_of_thread = %d\n", n); 441 for (i = 0; i < n; i++) { 442 if (!get_nth_lwp_regs(ph, i, ®s)) { 443 print_debug("Could not get regs of thread %d, already set!\n", i); 444 (*env)->ReleaseLongArrayElements(env, thrinfos, (jlong*)cinfos, 0); 445 return false; 446 } 447 for (j = 0; j < len; j += 3) { 448 lwpid_t uid = cinfos[j]; 449 uint64_t beg = cinfos[j + 1]; 450 uint64_t end = cinfos[j + 2]; 451 if ((regs.r_rsp < end && regs.r_rsp >= beg) || 452 (regs.r_rbp < end && regs.r_rbp >= beg)) { 453 set_lwp_id(ph, i, uid); 454 break; 455 } 456 } 457 } 458 (*env)->ReleaseLongArrayElements(env, thrinfos, (jlong*)cinfos, 0); 459 CHECK_EXCEPTION_(false); 460 return true; 461 } 462 463 /* For core file only, called from 464 * Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_getThreadIntegerRegisterSet0 465 */ 466 jlongArray getThreadIntegerRegisterSetFromCore(JNIEnv *env, jobject this_obj, long lwp_id, struct ps_prochandle* ph) { 467 if (!_threads_filled) { 468 if (!fill_java_threads(env, this_obj, ph)) { 469 throw_new_debugger_exception(env, "Failed to fill in threads"); 470 return 0; 471 } else { 472 _threads_filled = true; 473 } 474 } 475 476 struct reg gregs; 477 jboolean isCopy; 478 jlongArray array; 479 jlong *regs; 480 481 if (get_lwp_regs(ph, lwp_id, &gregs) != true) { 482 THROW_NEW_DEBUGGER_EXCEPTION_("get_thread_regs failed for a lwp", 0); 483 } 484 485 #undef NPRGREG 486 #undef REG_INDEX 487 #if amd64 488 #define NPRGREG sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_NPRGREG 489 #define REG_INDEX(reg) sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_##reg 490 491 array = (*env)->NewLongArray(env, NPRGREG); 492 CHECK_EXCEPTION_(0); 493 regs = (*env)->GetLongArrayElements(env, array, &isCopy); 494 495 regs[REG_INDEX(R15)] = gregs.r_r15; 496 regs[REG_INDEX(R14)] = gregs.r_r14; 497 regs[REG_INDEX(R13)] = gregs.r_r13; 498 regs[REG_INDEX(R12)] = gregs.r_r12; 499 regs[REG_INDEX(RBP)] = gregs.r_rbp; 500 regs[REG_INDEX(RBX)] = gregs.r_rbx; 501 regs[REG_INDEX(R11)] = gregs.r_r11; 502 regs[REG_INDEX(R10)] = gregs.r_r10; 503 regs[REG_INDEX(R9)] = gregs.r_r9; 504 regs[REG_INDEX(R8)] = gregs.r_r8; 505 regs[REG_INDEX(RAX)] = gregs.r_rax; 506 regs[REG_INDEX(RCX)] = gregs.r_rcx; 507 regs[REG_INDEX(RDX)] = gregs.r_rdx; 508 regs[REG_INDEX(RSI)] = gregs.r_rsi; 509 regs[REG_INDEX(RDI)] = gregs.r_rdi; 510 regs[REG_INDEX(RIP)] = gregs.r_rip; 511 regs[REG_INDEX(CS)] = gregs.r_cs; 512 regs[REG_INDEX(RSP)] = gregs.r_rsp; 513 regs[REG_INDEX(SS)] = gregs.r_ss; 514 regs[REG_INDEX(FSBASE)] = 0; 515 regs[REG_INDEX(GSBASE)] = 0; 516 regs[REG_INDEX(DS)] = gregs.r_ds; 517 regs[REG_INDEX(ES)] = gregs.r_es; 518 regs[REG_INDEX(FS)] = gregs.r_fs; 519 regs[REG_INDEX(GS)] = gregs.r_gs; 520 regs[REG_INDEX(TRAPNO)] = gregs.r_trapno; 521 regs[REG_INDEX(RFL)] = gregs.r_rflags; 522 523 (*env)->ReleaseLongArrayElements(env, array, regs, JNI_COMMIT); 524 #endif /* amd64 */ 525 return array; 526 } 527 528 /* 529 * Lookup the thread_t that corresponds to the given thread_id. 530 * The thread_id should be the result from calling thread_info() with THREAD_IDENTIFIER_INFO 531 * and reading the m_ident_info.thread_id returned. 532 * The returned thread_t is the mach send right to the kernel port for the corresponding thread. 533 * 534 * We cannot simply use the OSThread._thread_id field in the JVM. This is set to ::mach_thread_self() 535 * in the VM, but that thread port is not valid for a remote debugger to access the thread. 536 */ 537 thread_t 538 lookupThreadFromThreadId(task_t task, jlong thread_id) { 539 print_debug("lookupThreadFromThreadId thread_id=0x%llx\n", thread_id); 540 541 thread_array_t thread_list = NULL; 542 mach_msg_type_number_t thread_list_count = 0; 543 thread_t result_thread = 0; 544 int i; 545 546 // get the list of all the send rights 547 kern_return_t result = task_threads(task, &thread_list, &thread_list_count); 548 if (result != KERN_SUCCESS) { 549 print_debug("task_threads returned 0x%x\n", result); 550 return 0; 551 } 552 553 for(i = 0 ; i < thread_list_count; i++) { 554 thread_identifier_info_data_t m_ident_info; 555 mach_msg_type_number_t count = THREAD_IDENTIFIER_INFO_COUNT; 556 557 // get the THREAD_IDENTIFIER_INFO for the send right 558 result = thread_info(thread_list[i], THREAD_IDENTIFIER_INFO, (thread_info_t) &m_ident_info, &count); 559 if (result != KERN_SUCCESS) { 560 print_debug("thread_info returned 0x%x\n", result); 561 break; 562 } 563 564 // if this is the one we're looking for, return the send right 565 if (thread_id == m_ident_info.thread_id) 566 { 567 result_thread = thread_list[i]; 568 break; 569 } 570 } 571 572 vm_size_t thread_list_size = (vm_size_t) (thread_list_count * sizeof (thread_t)); 573 vm_deallocate(mach_task_self(), (vm_address_t) thread_list, thread_list_count); 574 575 return result_thread; 576 } 577 578 579 /* 580 * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal 581 * Method: getThreadIntegerRegisterSet0 582 * Signature: (J)[J 583 */ 584 JNIEXPORT jlongArray JNICALL 585 Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_getThreadIntegerRegisterSet0( 586 JNIEnv *env, jobject this_obj, 587 jlong thread_id) 588 { 589 print_debug("getThreadRegisterSet0 called\n"); 590 591 struct ps_prochandle* ph = get_proc_handle(env, this_obj); 592 if (ph != NULL && ph->core != NULL) { 593 return getThreadIntegerRegisterSetFromCore(env, this_obj, thread_id, ph); 594 } 595 596 kern_return_t result; 597 thread_t tid; 598 mach_msg_type_number_t count = HSDB_THREAD_STATE_COUNT; 599 hsdb_thread_state_t state; 600 jlongArray registerArray; 601 jlong *primitiveArray; 602 task_t gTask = getTask(env, this_obj); 603 604 tid = lookupThreadFromThreadId(gTask, thread_id); 605 606 result = thread_get_state(tid, HSDB_THREAD_STATE, (thread_state_t)&state, &count); 607 608 if (result != KERN_SUCCESS) { 609 print_error("getregs: thread_get_state(%d) failed (%d)\n", tid, result); 610 return NULL; 611 } 612 613 #if amd64 614 #define NPRGREG sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_NPRGREG 615 #undef REG_INDEX 616 #define REG_INDEX(reg) sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_##reg 617 618 // 64 bit 619 print_debug("Getting threads for a 64-bit process\n"); 620 registerArray = (*env)->NewLongArray(env, NPRGREG); 621 CHECK_EXCEPTION_(0); 622 primitiveArray = (*env)->GetLongArrayElements(env, registerArray, NULL); 623 624 primitiveArray[REG_INDEX(R15)] = state.__r15; 625 primitiveArray[REG_INDEX(R14)] = state.__r14; 626 primitiveArray[REG_INDEX(R13)] = state.__r13; 627 primitiveArray[REG_INDEX(R12)] = state.__r12; 628 primitiveArray[REG_INDEX(R11)] = state.__r11; 629 primitiveArray[REG_INDEX(R10)] = state.__r10; 630 primitiveArray[REG_INDEX(R9)] = state.__r9; 631 primitiveArray[REG_INDEX(R8)] = state.__r8; 632 primitiveArray[REG_INDEX(RDI)] = state.__rdi; 633 primitiveArray[REG_INDEX(RSI)] = state.__rsi; 634 primitiveArray[REG_INDEX(RBP)] = state.__rbp; 635 primitiveArray[REG_INDEX(RBX)] = state.__rbx; 636 primitiveArray[REG_INDEX(RDX)] = state.__rdx; 637 primitiveArray[REG_INDEX(RCX)] = state.__rcx; 638 primitiveArray[REG_INDEX(RAX)] = state.__rax; 639 primitiveArray[REG_INDEX(TRAPNO)] = 0; // trapno, not used 640 primitiveArray[REG_INDEX(ERR)] = 0; // err, not used 641 primitiveArray[REG_INDEX(RIP)] = state.__rip; 642 primitiveArray[REG_INDEX(CS)] = state.__cs; 643 primitiveArray[REG_INDEX(RFL)] = state.__rflags; 644 primitiveArray[REG_INDEX(RSP)] = state.__rsp; 645 primitiveArray[REG_INDEX(SS)] = 0; // We don't have SS 646 primitiveArray[REG_INDEX(FS)] = state.__fs; 647 primitiveArray[REG_INDEX(GS)] = state.__gs; 648 primitiveArray[REG_INDEX(ES)] = 0; 649 primitiveArray[REG_INDEX(DS)] = 0; 650 primitiveArray[REG_INDEX(FSBASE)] = 0; 651 primitiveArray[REG_INDEX(GSBASE)] = 0; 652 print_debug("set registers\n"); 653 654 (*env)->ReleaseLongArrayElements(env, registerArray, primitiveArray, 0); 655 656 #else 657 #error UNSUPPORTED_ARCH 658 #endif /* amd64 */ 659 660 return registerArray; 661 } 662 663 /* 664 * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal 665 * Method: translateTID0 666 * Signature: (I)I 667 */ 668 JNIEXPORT jint JNICALL 669 Java_sun_jvm_hotspot_debugger_macosx_MacOSXDebuggerLocal_translateTID0( 670 JNIEnv *env, jobject this_obj, jint tid) 671 { 672 print_debug("translateTID0 called on tid = 0x%x\n", (int)tid); 673 674 kern_return_t result; 675 thread_t foreign_tid, usable_tid; 676 mach_msg_type_name_t type; 677 678 foreign_tid = tid; 679 680 task_t gTask = getTask(env, this_obj); 681 result = mach_port_extract_right(gTask, foreign_tid, 682 MACH_MSG_TYPE_COPY_SEND, 683 &usable_tid, &type); 684 if (result != KERN_SUCCESS) 685 return -1; 686 687 print_debug("translateTID0: 0x%x -> 0x%x\n", foreign_tid, usable_tid); 688 689 return (jint) usable_tid; 690 } 691 692 // attach to a process/thread specified by "pid" 693 static bool ptrace_attach(pid_t pid) { 694 errno = 0; 695 ptrace(PT_ATTACHEXC, pid, 0, 0); 696 697 if (errno != 0) { 698 print_error("ptrace_attach: ptrace(PT_ATTACHEXC,...) failed: %s", strerror(errno)); 699 return false; 700 } 701 return true; 702 } 703 704 kern_return_t catch_mach_exception_raise( 705 mach_port_t exception_port, mach_port_t thread_port, mach_port_t task_port, 706 exception_type_t exception_type, mach_exception_data_t codes, 707 mach_msg_type_number_t num_codes) { 708 709 print_debug("catch_mach_exception_raise: Exception port = %d thread_port = %d " 710 "task port %d exc type = %d num_codes %d\n", 711 exception_port, thread_port, task_port, exception_type, num_codes); 712 713 // This message should denote a Unix soft signal, with 714 // 1. the exception type = EXC_SOFTWARE 715 // 2. codes[0] (which is the code) = EXC_SOFT_SIGNAL 716 // 3. codes[1] (which is the sub-code) = SIGSTOP 717 if (!(exception_type == EXC_SOFTWARE && 718 codes[0] == EXC_SOFT_SIGNAL && 719 codes[num_codes -1] == SIGSTOP)) { 720 print_error("catch_mach_exception_raise: Message doesn't denote a Unix " 721 "soft signal. exception_type = %d, codes[0] = %d, " 722 "codes[num_codes -1] = %d, num_codes = %d\n", 723 exception_type, codes[0], codes[num_codes - 1], num_codes); 724 return MACH_RCV_INVALID_TYPE; 725 } 726 return KERN_SUCCESS; 727 } 728 729 kern_return_t catch_mach_exception_raise_state( 730 mach_port_t exception_port, exception_type_t exception, const mach_exception_data_t code, 731 mach_msg_type_number_t code_cnt, int *flavor, const thread_state_t old_state, 732 mach_msg_type_number_t old_state_cnt, thread_state_t new_state, 733 mach_msg_type_number_t *new_state_cnt) { 734 return MACH_RCV_INVALID_TYPE; 735 } 736 737 738 kern_return_t catch_mach_exception_raise_state_identity( 739 mach_port_t exception_port, mach_port_t thread, mach_port_t task, 740 exception_type_t exception, mach_exception_data_t code, 741 mach_msg_type_number_t code_cnt, int *flavor, 742 thread_state_t old_state, mach_msg_type_number_t old_state_cnt, 743 thread_state_t new_state, mach_msg_type_number_t *new_state_cnt) { 744 return MACH_RCV_INVALID_TYPE; 745 } 746 747 // wait to receive an exception message 748 static bool wait_for_exception() { 749 kern_return_t result; 750 751 result = mach_msg(&exc_msg.header, 752 MACH_RCV_MSG, 753 0, 754 sizeof(exc_msg), 755 tgt_exception_port, 756 MACH_MSG_TIMEOUT_NONE, 757 MACH_PORT_NULL); 758 759 if (result != MACH_MSG_SUCCESS) { 760 print_error("attach: wait_for_exception: mach_msg() failed: '%s' (%d)\n", 761 mach_error_string(result), result); 762 return false; 763 } 764 765 if (mach_exc_server(&exc_msg.header, &rep_msg.header) == false || 766 rep_msg.ret_code != KERN_SUCCESS) { 767 print_error("attach: wait_for_exception: mach_exc_server failure\n"); 768 if (rep_msg.ret_code != KERN_SUCCESS) { 769 print_error("catch_mach_exception_raise() failed '%s' (%d)\n", 770 mach_error_string(rep_msg.ret_code), rep_msg.ret_code); 771 } 772 return false; 773 } 774 775 print_debug("reply msg from mach_exc_server: (msg->{bits = %#x, size = %u, " 776 "remote_port = %#x, local_port = %#x, reserved = 0x%x, id = 0x%x},)", 777 rep_msg.header.msgh_bits, rep_msg.header.msgh_size, 778 rep_msg.header.msgh_remote_port, rep_msg.header.msgh_local_port, 779 rep_msg.header.msgh_reserved, rep_msg.header.msgh_id); 780 781 return true; 782 } 783 784 /* 785 * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal 786 * Method: attach0 787 * Signature: (I)V 788 */ 789 JNIEXPORT void JNICALL 790 Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_attach0__I( 791 JNIEnv *env, jobject this_obj, jint jpid) 792 { 793 print_debug("attach0 called for jpid=%d\n", (int)jpid); 794 795 JNF_COCOA_ENTER(env); 796 797 kern_return_t result; 798 task_t gTask = 0; 799 800 result = task_for_pid(mach_task_self(), jpid, &gTask); 801 if (result != KERN_SUCCESS) { 802 print_error("attach: task_for_pid(%d) failed: '%s' (%d)\n", (int)jpid, mach_error_string(result), result); 803 THROW_NEW_DEBUGGER_EXCEPTION( 804 "Can't attach to the process. Could be caused by an incorrect pid or lack of privileges."); 805 } 806 putTask(env, this_obj, gTask); 807 808 // Allocate an exception port. 809 result = mach_port_allocate(mach_task_self(), 810 MACH_PORT_RIGHT_RECEIVE, 811 &tgt_exception_port); 812 if (result != KERN_SUCCESS) { 813 print_error("attach: mach_port_allocate() for tgt_exception_port failed: '%s' (%d)\n", 814 mach_error_string(result), result); 815 THROW_NEW_DEBUGGER_EXCEPTION( 816 "Can't attach to the process. Couldn't allocate an exception port."); 817 } 818 819 // Enable the new exception port to send messages. 820 result = mach_port_insert_right (mach_task_self(), 821 tgt_exception_port, 822 tgt_exception_port, 823 MACH_MSG_TYPE_MAKE_SEND); 824 if (result != KERN_SUCCESS) { 825 print_error("attach: mach_port_insert_right() failed for port 0x%x: '%s' (%d)\n", 826 tgt_exception_port, mach_error_string(result), result); 827 THROW_NEW_DEBUGGER_EXCEPTION( 828 "Can't attach to the process. Couldn't add send privileges to the exception port."); 829 } 830 831 // Save the existing original exception ports registered with the target 832 // process (for later restoration while detaching from the process). 833 result = task_get_exception_ports(gTask, 834 EXC_MASK_ALL, 835 exception_saved_state.saved_masks, 836 &exception_saved_state.saved_exception_types_count, 837 exception_saved_state.saved_ports, 838 exception_saved_state.saved_behaviors, 839 exception_saved_state.saved_flavors); 840 841 if (result != KERN_SUCCESS) { 842 print_error("attach: task_get_exception_ports() failed: '%s' (%d)\n", 843 mach_error_string(result), result); 844 THROW_NEW_DEBUGGER_EXCEPTION( 845 "Can't attach to the process. Could not get the target exception ports."); 846 } 847 848 // register the exception port to be used for all future exceptions with the 849 // target process. 850 result = task_set_exception_ports(gTask, 851 EXC_MASK_ALL, 852 tgt_exception_port, 853 EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES, 854 THREAD_STATE_NONE); 855 856 if (result != KERN_SUCCESS) { 857 print_error("attach: task_set_exception_ports() failed -- port 0x%x: '%s' (%d)\n", 858 tgt_exception_port, mach_error_string(result), result); 859 mach_port_deallocate(mach_task_self(), gTask); 860 mach_port_deallocate(mach_task_self(), tgt_exception_port); 861 THROW_NEW_DEBUGGER_EXCEPTION( 862 "Can't attach to the process. Could not register the exception port " 863 "with the target process."); 864 } 865 866 // use ptrace to stop the process 867 // on os x, ptrace only needs to be called on the process, not the individual threads 868 if (ptrace_attach(jpid) != true) { 869 print_error("attach: ptrace failure in attaching to %d\n", (int)jpid); 870 mach_port_deallocate(mach_task_self(), gTask); 871 mach_port_deallocate(mach_task_self(), tgt_exception_port); 872 THROW_NEW_DEBUGGER_EXCEPTION("Can't ptrace attach to the process"); 873 } 874 875 if (wait_for_exception() != true) { 876 mach_port_deallocate(mach_task_self(), gTask); 877 mach_port_deallocate(mach_task_self(), tgt_exception_port); 878 THROW_NEW_DEBUGGER_EXCEPTION( 879 "Can't attach to the process. Issues with reception of the exception message."); 880 } 881 882 // suspend all the threads in the task 883 result = task_suspend(gTask); 884 if (result != KERN_SUCCESS) { 885 print_error("attach: task_suspend() failed: '%s' (%d)\n", 886 mach_error_string(result), result); 887 mach_port_deallocate(mach_task_self(), gTask); 888 mach_port_deallocate(mach_task_self(), tgt_exception_port); 889 THROW_NEW_DEBUGGER_EXCEPTION("Can't attach. Unable to suspend all the threads in the task."); 890 } 891 892 id symbolicator = nil; 893 id jrsSymbolicator = objc_lookUpClass("JRSSymbolicator"); 894 if (jrsSymbolicator != nil) { 895 id (*dynamicCall)(id, SEL, pid_t) = (id (*)(id, SEL, pid_t))&objc_msgSend; 896 symbolicator = dynamicCall(jrsSymbolicator, @selector(symbolicatorForPid:), (pid_t)jpid); 897 } 898 if (symbolicator != nil) { 899 CFRetain(symbolicator); // pin symbolicator while in java heap 900 } 901 902 putSymbolicator(env, this_obj, symbolicator); 903 if (symbolicator == nil) { 904 mach_port_deallocate(mach_task_self(), gTask); 905 mach_port_deallocate(mach_task_self(), tgt_exception_port); 906 THROW_NEW_DEBUGGER_EXCEPTION("Can't attach symbolicator to the process"); 907 } 908 909 JNF_COCOA_EXIT(env); 910 } 911 912 /** For core file, 913 called from Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_attach0__Ljava_lang_String_2Ljava_lang_String_2 */ 914 static void fillLoadObjects(JNIEnv* env, jobject this_obj, struct ps_prochandle* ph) { 915 int n = 0, i = 0; 916 917 // add load objects 918 n = get_num_libs(ph); 919 for (i = 0; i < n; i++) { 920 uintptr_t base; 921 const char* name; 922 jobject loadObject; 923 jobject loadObjectList; 924 jstring nameString; 925 926 base = get_lib_base(ph, i); 927 name = get_lib_name(ph, i); 928 nameString = (*env)->NewStringUTF(env, name); 929 CHECK_EXCEPTION; 930 loadObject = (*env)->CallObjectMethod(env, this_obj, createLoadObject_ID, 931 nameString, (jlong)0, (jlong)base); 932 CHECK_EXCEPTION; 933 loadObjectList = (*env)->GetObjectField(env, this_obj, loadObjectList_ID); 934 CHECK_EXCEPTION; 935 (*env)->CallBooleanMethod(env, loadObjectList, listAdd_ID, loadObject); 936 CHECK_EXCEPTION; 937 } 938 } 939 940 /* 941 * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal 942 * Method: attach0 943 * Signature: (Ljava/lang/String;Ljava/lang/String;)V 944 */ 945 JNIEXPORT void JNICALL 946 Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_attach0__Ljava_lang_String_2Ljava_lang_String_2( 947 JNIEnv *env, jobject this_obj, jstring execName, jstring coreName) 948 { 949 const char *execName_cstr; 950 const char *coreName_cstr; 951 jboolean isCopy; 952 struct ps_prochandle* ph; 953 954 execName_cstr = (*env)->GetStringUTFChars(env, execName, &isCopy); 955 CHECK_EXCEPTION; 956 coreName_cstr = (*env)->GetStringUTFChars(env, coreName, &isCopy); 957 CHECK_EXCEPTION; 958 959 print_debug("attach: %s %s\n", execName_cstr, coreName_cstr); 960 961 if ( (ph = Pgrab_core(execName_cstr, coreName_cstr)) == NULL) { 962 (*env)->ReleaseStringUTFChars(env, execName, execName_cstr); 963 (*env)->ReleaseStringUTFChars(env, coreName, coreName_cstr); 964 THROW_NEW_DEBUGGER_EXCEPTION("Can't attach to the core file"); 965 } 966 (*env)->SetLongField(env, this_obj, p_ps_prochandle_ID, (jlong)(intptr_t)ph); 967 (*env)->ReleaseStringUTFChars(env, execName, execName_cstr); 968 (*env)->ReleaseStringUTFChars(env, coreName, coreName_cstr); 969 fillLoadObjects(env, this_obj, ph); 970 } 971 972 static void detach_cleanup(task_t gTask, JNIEnv *env, jobject this_obj, bool throw_exception) { 973 mach_port_deallocate(mach_task_self(), tgt_exception_port); 974 mach_port_deallocate(mach_task_self(), gTask); 975 976 id symbolicator = getSymbolicator(env, this_obj); 977 if (symbolicator != nil) { 978 CFRelease(symbolicator); 979 } 980 if (throw_exception) { 981 THROW_NEW_DEBUGGER_EXCEPTION("Cannot detach."); 982 } 983 } 984 985 /* 986 * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal 987 * Method: detach0 988 * Signature: ()V 989 */ 990 JNIEXPORT void JNICALL 991 Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_detach0( 992 JNIEnv *env, jobject this_obj) 993 { 994 print_debug("detach0 called\n"); 995 struct ps_prochandle* ph = get_proc_handle(env, this_obj); 996 if (ph != NULL && ph->core != NULL) { 997 Prelease(ph); 998 return; 999 } 1000 JNF_COCOA_ENTER(env); 1001 1002 task_t gTask = getTask(env, this_obj); 1003 kern_return_t k_res = 0; 1004 1005 // Restore the pre-saved original exception ports registered with the target process 1006 for (uint32_t i = 0; i < exception_saved_state.saved_exception_types_count; ++i) { 1007 k_res = task_set_exception_ports(gTask, 1008 exception_saved_state.saved_masks[i], 1009 exception_saved_state.saved_ports[i], 1010 exception_saved_state.saved_behaviors[i], 1011 exception_saved_state.saved_flavors[i]); 1012 if (k_res != KERN_SUCCESS) { 1013 print_error("detach: task_set_exception_ports failed with %d while " 1014 "restoring the target exception ports.\n", k_res); 1015 detach_cleanup(gTask, env, this_obj, true); 1016 } 1017 } 1018 1019 // detach from the ptraced process causing it to resume execution 1020 int pid; 1021 k_res = pid_for_task(gTask, &pid); 1022 if (k_res != KERN_SUCCESS) { 1023 print_error("detach: pid_for_task(%d) failed (%d)\n", pid, k_res); 1024 detach_cleanup(gTask, env, this_obj, true); 1025 } 1026 else { 1027 errno = 0; 1028 ptrace(PT_DETACH, pid, (caddr_t)1, 0); 1029 if (errno != 0) { 1030 print_error("detach: ptrace(PT_DETACH,...) failed: %s", strerror(errno)); 1031 detach_cleanup(gTask, env, this_obj, true); 1032 } 1033 } 1034 1035 // reply to the previous exception message 1036 k_res = mach_msg(&rep_msg.header, 1037 MACH_SEND_MSG| MACH_SEND_INTERRUPT, 1038 rep_msg.header.msgh_size, 1039 0, 1040 MACH_PORT_NULL, 1041 MACH_MSG_TIMEOUT_NONE, 1042 MACH_PORT_NULL); 1043 if (k_res != MACH_MSG_SUCCESS) { 1044 print_error("detach: mach_msg() for replying to pending exceptions failed: '%s' (%d)\n", 1045 mach_error_string(k_res), k_res); 1046 detach_cleanup(gTask, env, this_obj, true); 1047 } 1048 1049 detach_cleanup(gTask, env, this_obj, false); 1050 1051 JNF_COCOA_EXIT(env); 1052 }