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 return false; 445 } 446 for (j = 0; j < len; j += 3) { 447 lwpid_t uid = cinfos[j]; 448 uint64_t beg = cinfos[j + 1]; 449 uint64_t end = cinfos[j + 2]; 450 if ((regs.r_rsp < end && regs.r_rsp >= beg) || 451 (regs.r_rbp < end && regs.r_rbp >= beg)) { 452 set_lwp_id(ph, i, uid); 453 break; 454 } 455 } 456 } 457 (*env)->ReleaseLongArrayElements(env, thrinfos, (jlong*)cinfos, 0); 458 CHECK_EXCEPTION_(false); 459 return true; 460 } 461 462 /* For core file only, called from 463 * Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_getThreadIntegerRegisterSet0 464 */ 465 jlongArray getThreadIntegerRegisterSetFromCore(JNIEnv *env, jobject this_obj, long lwp_id, struct ps_prochandle* ph) { 466 if (!_threads_filled) { 467 if (!fill_java_threads(env, this_obj, ph)) { 468 throw_new_debugger_exception(env, "Failed to fill in threads"); 469 return 0; 470 } else { 471 _threads_filled = true; 472 } 473 } 474 475 struct reg gregs; 476 jboolean isCopy; 477 jlongArray array; 478 jlong *regs; 479 480 if (get_lwp_regs(ph, lwp_id, &gregs) != true) { 481 THROW_NEW_DEBUGGER_EXCEPTION_("get_thread_regs failed for a lwp", 0); 482 } 483 484 #undef NPRGREG 485 #undef REG_INDEX 486 #if amd64 487 #define NPRGREG sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_NPRGREG 488 #define REG_INDEX(reg) sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_##reg 489 490 array = (*env)->NewLongArray(env, NPRGREG); 491 CHECK_EXCEPTION_(0); 492 regs = (*env)->GetLongArrayElements(env, array, &isCopy); 493 494 regs[REG_INDEX(R15)] = gregs.r_r15; 495 regs[REG_INDEX(R14)] = gregs.r_r14; 496 regs[REG_INDEX(R13)] = gregs.r_r13; 497 regs[REG_INDEX(R12)] = gregs.r_r12; 498 regs[REG_INDEX(RBP)] = gregs.r_rbp; 499 regs[REG_INDEX(RBX)] = gregs.r_rbx; 500 regs[REG_INDEX(R11)] = gregs.r_r11; 501 regs[REG_INDEX(R10)] = gregs.r_r10; 502 regs[REG_INDEX(R9)] = gregs.r_r9; 503 regs[REG_INDEX(R8)] = gregs.r_r8; 504 regs[REG_INDEX(RAX)] = gregs.r_rax; 505 regs[REG_INDEX(RCX)] = gregs.r_rcx; 506 regs[REG_INDEX(RDX)] = gregs.r_rdx; 507 regs[REG_INDEX(RSI)] = gregs.r_rsi; 508 regs[REG_INDEX(RDI)] = gregs.r_rdi; 509 regs[REG_INDEX(RIP)] = gregs.r_rip; 510 regs[REG_INDEX(CS)] = gregs.r_cs; 511 regs[REG_INDEX(RSP)] = gregs.r_rsp; 512 regs[REG_INDEX(SS)] = gregs.r_ss; 513 regs[REG_INDEX(FSBASE)] = 0; 514 regs[REG_INDEX(GSBASE)] = 0; 515 regs[REG_INDEX(DS)] = gregs.r_ds; 516 regs[REG_INDEX(ES)] = gregs.r_es; 517 regs[REG_INDEX(FS)] = gregs.r_fs; 518 regs[REG_INDEX(GS)] = gregs.r_gs; 519 regs[REG_INDEX(TRAPNO)] = gregs.r_trapno; 520 regs[REG_INDEX(RFL)] = gregs.r_rflags; 521 522 #endif /* amd64 */ 523 (*env)->ReleaseLongArrayElements(env, array, regs, JNI_COMMIT); 524 return array; 525 } 526 527 /* 528 * Lookup the thread_t that corresponds to the given thread_id. 529 * The thread_id should be the result from calling thread_info() with THREAD_IDENTIFIER_INFO 530 * and reading the m_ident_info.thread_id returned. 531 * The returned thread_t is the mach send right to the kernel port for the corresponding thread. 532 * 533 * We cannot simply use the OSThread._thread_id field in the JVM. This is set to ::mach_thread_self() 534 * in the VM, but that thread port is not valid for a remote debugger to access the thread. 535 */ 536 thread_t 537 lookupThreadFromThreadId(task_t task, jlong thread_id) { 538 print_debug("lookupThreadFromThreadId thread_id=0x%llx\n", thread_id); 539 540 thread_array_t thread_list = NULL; 541 mach_msg_type_number_t thread_list_count = 0; 542 thread_t result_thread = 0; 543 int i; 544 545 // get the list of all the send rights 546 kern_return_t result = task_threads(task, &thread_list, &thread_list_count); 547 if (result != KERN_SUCCESS) { 548 print_debug("task_threads returned 0x%x\n", result); 549 return 0; 550 } 551 552 for(i = 0 ; i < thread_list_count; i++) { 553 thread_identifier_info_data_t m_ident_info; 554 mach_msg_type_number_t count = THREAD_IDENTIFIER_INFO_COUNT; 555 556 // get the THREAD_IDENTIFIER_INFO for the send right 557 result = thread_info(thread_list[i], THREAD_IDENTIFIER_INFO, (thread_info_t) &m_ident_info, &count); 558 if (result != KERN_SUCCESS) { 559 print_debug("thread_info returned 0x%x\n", result); 560 break; 561 } 562 563 // if this is the one we're looking for, return the send right 564 if (thread_id == m_ident_info.thread_id) 565 { 566 result_thread = thread_list[i]; 567 break; 568 } 569 } 570 571 vm_size_t thread_list_size = (vm_size_t) (thread_list_count * sizeof (thread_t)); 572 vm_deallocate(mach_task_self(), (vm_address_t) thread_list, thread_list_count); 573 574 return result_thread; 575 } 576 577 578 /* 579 * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal 580 * Method: getThreadIntegerRegisterSet0 581 * Signature: (J)[J 582 */ 583 JNIEXPORT jlongArray JNICALL 584 Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_getThreadIntegerRegisterSet0( 585 JNIEnv *env, jobject this_obj, 586 jlong thread_id) 587 { 588 print_debug("getThreadRegisterSet0 called\n"); 589 590 struct ps_prochandle* ph = get_proc_handle(env, this_obj); 591 if (ph != NULL && ph->core != NULL) { 592 return getThreadIntegerRegisterSetFromCore(env, this_obj, thread_id, ph); 593 } 594 595 kern_return_t result; 596 thread_t tid; 597 mach_msg_type_number_t count = HSDB_THREAD_STATE_COUNT; 598 hsdb_thread_state_t state; 599 jlongArray registerArray; 600 jlong *primitiveArray; 601 task_t gTask = getTask(env, this_obj); 602 603 tid = lookupThreadFromThreadId(gTask, thread_id); 604 605 result = thread_get_state(tid, HSDB_THREAD_STATE, (thread_state_t)&state, &count); 606 607 if (result != KERN_SUCCESS) { 608 print_error("getregs: thread_get_state(%d) failed (%d)\n", tid, result); 609 return NULL; 610 } 611 612 #if amd64 613 #define NPRGREG sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_NPRGREG 614 #undef REG_INDEX 615 #define REG_INDEX(reg) sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_##reg 616 617 // 64 bit 618 print_debug("Getting threads for a 64-bit process\n"); 619 registerArray = (*env)->NewLongArray(env, NPRGREG); 620 CHECK_EXCEPTION_(0); 621 primitiveArray = (*env)->GetLongArrayElements(env, registerArray, NULL); 622 623 primitiveArray[REG_INDEX(R15)] = state.__r15; 624 primitiveArray[REG_INDEX(R14)] = state.__r14; 625 primitiveArray[REG_INDEX(R13)] = state.__r13; 626 primitiveArray[REG_INDEX(R12)] = state.__r12; 627 primitiveArray[REG_INDEX(R11)] = state.__r11; 628 primitiveArray[REG_INDEX(R10)] = state.__r10; 629 primitiveArray[REG_INDEX(R9)] = state.__r9; 630 primitiveArray[REG_INDEX(R8)] = state.__r8; 631 primitiveArray[REG_INDEX(RDI)] = state.__rdi; 632 primitiveArray[REG_INDEX(RSI)] = state.__rsi; 633 primitiveArray[REG_INDEX(RBP)] = state.__rbp; 634 primitiveArray[REG_INDEX(RBX)] = state.__rbx; 635 primitiveArray[REG_INDEX(RDX)] = state.__rdx; 636 primitiveArray[REG_INDEX(RCX)] = state.__rcx; 637 primitiveArray[REG_INDEX(RAX)] = state.__rax; 638 primitiveArray[REG_INDEX(TRAPNO)] = 0; // trapno, not used 639 primitiveArray[REG_INDEX(ERR)] = 0; // err, not used 640 primitiveArray[REG_INDEX(RIP)] = state.__rip; 641 primitiveArray[REG_INDEX(CS)] = state.__cs; 642 primitiveArray[REG_INDEX(RFL)] = state.__rflags; 643 primitiveArray[REG_INDEX(RSP)] = state.__rsp; 644 primitiveArray[REG_INDEX(SS)] = 0; // We don't have SS 645 primitiveArray[REG_INDEX(FS)] = state.__fs; 646 primitiveArray[REG_INDEX(GS)] = state.__gs; 647 primitiveArray[REG_INDEX(ES)] = 0; 648 primitiveArray[REG_INDEX(DS)] = 0; 649 primitiveArray[REG_INDEX(FSBASE)] = 0; 650 primitiveArray[REG_INDEX(GSBASE)] = 0; 651 print_debug("set registers\n"); 652 653 (*env)->ReleaseLongArrayElements(env, registerArray, primitiveArray, 0); 654 655 #else 656 #error UNSUPPORTED_ARCH 657 #endif /* amd64 */ 658 659 return registerArray; 660 } 661 662 /* 663 * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal 664 * Method: translateTID0 665 * Signature: (I)I 666 */ 667 JNIEXPORT jint JNICALL 668 Java_sun_jvm_hotspot_debugger_macosx_MacOSXDebuggerLocal_translateTID0( 669 JNIEnv *env, jobject this_obj, jint tid) 670 { 671 print_debug("translateTID0 called on tid = 0x%x\n", (int)tid); 672 673 kern_return_t result; 674 thread_t foreign_tid, usable_tid; 675 mach_msg_type_name_t type; 676 677 foreign_tid = tid; 678 679 task_t gTask = getTask(env, this_obj); 680 result = mach_port_extract_right(gTask, foreign_tid, 681 MACH_MSG_TYPE_COPY_SEND, 682 &usable_tid, &type); 683 if (result != KERN_SUCCESS) 684 return -1; 685 686 print_debug("translateTID0: 0x%x -> 0x%x\n", foreign_tid, usable_tid); 687 688 return (jint) usable_tid; 689 } 690 691 // attach to a process/thread specified by "pid" 692 static bool ptrace_attach(pid_t pid) { 693 errno = 0; 694 ptrace(PT_ATTACHEXC, pid, 0, 0); 695 696 if (errno != 0) { 697 print_error("ptrace_attach: ptrace(PT_ATTACHEXC,...) failed: %s", strerror(errno)); 698 return false; 699 } 700 return true; 701 } 702 703 kern_return_t catch_mach_exception_raise( 704 mach_port_t exception_port, mach_port_t thread_port, mach_port_t task_port, 705 exception_type_t exception_type, mach_exception_data_t codes, 706 mach_msg_type_number_t num_codes) { 707 708 print_debug("catch_mach_exception_raise: Exception port = %d thread_port = %d " 709 "task port %d exc type = %d num_codes %d\n", 710 exception_port, thread_port, task_port, exception_type, num_codes); 711 712 // This message should denote a Unix soft signal, with 713 // 1. the exception type = EXC_SOFTWARE 714 // 2. codes[0] (which is the code) = EXC_SOFT_SIGNAL 715 // 3. codes[1] (which is the sub-code) = SIGSTOP 716 if (!(exception_type == EXC_SOFTWARE && 717 codes[0] == EXC_SOFT_SIGNAL && 718 codes[num_codes -1] == SIGSTOP)) { 719 print_error("catch_mach_exception_raise: Message doesn't denote a Unix " 720 "soft signal. exception_type = %d, codes[0] = %d, " 721 "codes[num_codes -1] = %d, num_codes = %d\n", 722 exception_type, codes[0], codes[num_codes - 1], num_codes); 723 return MACH_RCV_INVALID_TYPE; 724 } 725 return KERN_SUCCESS; 726 } 727 728 kern_return_t catch_mach_exception_raise_state( 729 mach_port_t exception_port, exception_type_t exception, const mach_exception_data_t code, 730 mach_msg_type_number_t code_cnt, int *flavor, const thread_state_t old_state, 731 mach_msg_type_number_t old_state_cnt, thread_state_t new_state, 732 mach_msg_type_number_t *new_state_cnt) { 733 return MACH_RCV_INVALID_TYPE; 734 } 735 736 737 kern_return_t catch_mach_exception_raise_state_identity( 738 mach_port_t exception_port, mach_port_t thread, mach_port_t task, 739 exception_type_t exception, mach_exception_data_t code, 740 mach_msg_type_number_t code_cnt, int *flavor, 741 thread_state_t old_state, mach_msg_type_number_t old_state_cnt, 742 thread_state_t new_state, mach_msg_type_number_t *new_state_cnt) { 743 return MACH_RCV_INVALID_TYPE; 744 } 745 746 // wait to receive an exception message 747 static bool wait_for_exception() { 748 kern_return_t result; 749 750 result = mach_msg(&exc_msg.header, 751 MACH_RCV_MSG, 752 0, 753 sizeof(exc_msg), 754 tgt_exception_port, 755 MACH_MSG_TIMEOUT_NONE, 756 MACH_PORT_NULL); 757 758 if (result != MACH_MSG_SUCCESS) { 759 print_error("attach: wait_for_exception: mach_msg() failed: '%s' (%d)\n", 760 mach_error_string(result), result); 761 return false; 762 } 763 764 if (mach_exc_server(&exc_msg.header, &rep_msg.header) == false || 765 rep_msg.ret_code != KERN_SUCCESS) { 766 print_error("attach: wait_for_exception: mach_exc_server failure\n"); 767 if (rep_msg.ret_code != KERN_SUCCESS) { 768 print_error("catch_mach_exception_raise() failed '%s' (%d)\n", 769 mach_error_string(rep_msg.ret_code), rep_msg.ret_code); 770 } 771 return false; 772 } 773 774 print_debug("reply msg from mach_exc_server: (msg->{bits = %#x, size = %u, " 775 "remote_port = %#x, local_port = %#x, reserved = 0x%x, id = 0x%x},)", 776 rep_msg.header.msgh_bits, rep_msg.header.msgh_size, 777 rep_msg.header.msgh_remote_port, rep_msg.header.msgh_local_port, 778 rep_msg.header.msgh_reserved, rep_msg.header.msgh_id); 779 780 return true; 781 } 782 783 /* 784 * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal 785 * Method: attach0 786 * Signature: (I)V 787 */ 788 JNIEXPORT void JNICALL 789 Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_attach0__I( 790 JNIEnv *env, jobject this_obj, jint jpid) 791 { 792 print_debug("attach0 called for jpid=%d\n", (int)jpid); 793 794 JNF_COCOA_ENTER(env); 795 796 kern_return_t result; 797 task_t gTask = 0; 798 799 result = task_for_pid(mach_task_self(), jpid, &gTask); 800 if (result != KERN_SUCCESS) { 801 print_error("attach: task_for_pid(%d) failed: '%s' (%d)\n", (int)jpid, mach_error_string(result), result); 802 THROW_NEW_DEBUGGER_EXCEPTION( 803 "Can't attach to the process. Could be caused by an incorrect pid or lack of privileges."); 804 } 805 putTask(env, this_obj, gTask); 806 807 // Allocate an exception port. 808 result = mach_port_allocate(mach_task_self(), 809 MACH_PORT_RIGHT_RECEIVE, 810 &tgt_exception_port); 811 if (result != KERN_SUCCESS) { 812 print_error("attach: mach_port_allocate() for tgt_exception_port failed: '%s' (%d)\n", 813 mach_error_string(result), result); 814 THROW_NEW_DEBUGGER_EXCEPTION( 815 "Can't attach to the process. Couldn't allocate an exception port."); 816 } 817 818 // Enable the new exception port to send messages. 819 result = mach_port_insert_right (mach_task_self(), 820 tgt_exception_port, 821 tgt_exception_port, 822 MACH_MSG_TYPE_MAKE_SEND); 823 if (result != KERN_SUCCESS) { 824 print_error("attach: mach_port_insert_right() failed for port 0x%x: '%s' (%d)\n", 825 tgt_exception_port, mach_error_string(result), result); 826 THROW_NEW_DEBUGGER_EXCEPTION( 827 "Can't attach to the process. Couldn't add send privileges to the exception port."); 828 } 829 830 // Save the existing original exception ports registered with the target 831 // process (for later restoration while detaching from the process). 832 result = task_get_exception_ports(gTask, 833 EXC_MASK_ALL, 834 exception_saved_state.saved_masks, 835 &exception_saved_state.saved_exception_types_count, 836 exception_saved_state.saved_ports, 837 exception_saved_state.saved_behaviors, 838 exception_saved_state.saved_flavors); 839 840 if (result != KERN_SUCCESS) { 841 print_error("attach: task_get_exception_ports() failed: '%s' (%d)\n", 842 mach_error_string(result), result); 843 THROW_NEW_DEBUGGER_EXCEPTION( 844 "Can't attach to the process. Could not get the target exception ports."); 845 } 846 847 // register the exception port to be used for all future exceptions with the 848 // target process. 849 result = task_set_exception_ports(gTask, 850 EXC_MASK_ALL, 851 tgt_exception_port, 852 EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES, 853 THREAD_STATE_NONE); 854 855 if (result != KERN_SUCCESS) { 856 print_error("attach: task_set_exception_ports() failed -- port 0x%x: '%s' (%d)\n", 857 tgt_exception_port, mach_error_string(result), result); 858 mach_port_deallocate(mach_task_self(), gTask); 859 mach_port_deallocate(mach_task_self(), tgt_exception_port); 860 THROW_NEW_DEBUGGER_EXCEPTION( 861 "Can't attach to the process. Could not register the exception port " 862 "with the target process."); 863 } 864 865 // use ptrace to stop the process 866 // on os x, ptrace only needs to be called on the process, not the individual threads 867 if (ptrace_attach(jpid) != true) { 868 print_error("attach: ptrace failure in attaching to %d\n", (int)jpid); 869 mach_port_deallocate(mach_task_self(), gTask); 870 mach_port_deallocate(mach_task_self(), tgt_exception_port); 871 THROW_NEW_DEBUGGER_EXCEPTION("Can't ptrace attach to the process"); 872 } 873 874 if (wait_for_exception() != true) { 875 mach_port_deallocate(mach_task_self(), gTask); 876 mach_port_deallocate(mach_task_self(), tgt_exception_port); 877 THROW_NEW_DEBUGGER_EXCEPTION( 878 "Can't attach to the process. Issues with reception of the exception message."); 879 } 880 881 // suspend all the threads in the task 882 result = task_suspend(gTask); 883 if (result != KERN_SUCCESS) { 884 print_error("attach: task_suspend() failed: '%s' (%d)\n", 885 mach_error_string(result), result); 886 mach_port_deallocate(mach_task_self(), gTask); 887 mach_port_deallocate(mach_task_self(), tgt_exception_port); 888 THROW_NEW_DEBUGGER_EXCEPTION("Can't attach. Unable to suspend all the threads in the task."); 889 } 890 891 id symbolicator = nil; 892 id jrsSymbolicator = objc_lookUpClass("JRSSymbolicator"); 893 if (jrsSymbolicator != nil) { 894 id (*dynamicCall)(id, SEL, pid_t) = (id (*)(id, SEL, pid_t))&objc_msgSend; 895 symbolicator = dynamicCall(jrsSymbolicator, @selector(symbolicatorForPid:), (pid_t)jpid); 896 } 897 if (symbolicator != nil) { 898 CFRetain(symbolicator); // pin symbolicator while in java heap 899 } 900 901 putSymbolicator(env, this_obj, symbolicator); 902 if (symbolicator == nil) { 903 mach_port_deallocate(mach_task_self(), gTask); 904 mach_port_deallocate(mach_task_self(), tgt_exception_port); 905 THROW_NEW_DEBUGGER_EXCEPTION("Can't attach symbolicator to the process"); 906 } 907 908 JNF_COCOA_EXIT(env); 909 } 910 911 /** For core file, 912 called from Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_attach0__Ljava_lang_String_2Ljava_lang_String_2 */ 913 static void fillLoadObjects(JNIEnv* env, jobject this_obj, struct ps_prochandle* ph) { 914 int n = 0, i = 0; 915 916 // add load objects 917 n = get_num_libs(ph); 918 for (i = 0; i < n; i++) { 919 uintptr_t base; 920 const char* name; 921 jobject loadObject; 922 jobject loadObjectList; 923 jstring nameString; 924 925 base = get_lib_base(ph, i); 926 name = get_lib_name(ph, i); 927 nameString = (*env)->NewStringUTF(env, name); 928 CHECK_EXCEPTION; 929 loadObject = (*env)->CallObjectMethod(env, this_obj, createLoadObject_ID, 930 nameString, (jlong)0, (jlong)base); 931 CHECK_EXCEPTION; 932 loadObjectList = (*env)->GetObjectField(env, this_obj, loadObjectList_ID); 933 CHECK_EXCEPTION; 934 (*env)->CallBooleanMethod(env, loadObjectList, listAdd_ID, loadObject); 935 CHECK_EXCEPTION; 936 } 937 } 938 939 /* 940 * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal 941 * Method: attach0 942 * Signature: (Ljava/lang/String;Ljava/lang/String;)V 943 */ 944 JNIEXPORT void JNICALL 945 Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_attach0__Ljava_lang_String_2Ljava_lang_String_2( 946 JNIEnv *env, jobject this_obj, jstring execName, jstring coreName) 947 { 948 const char *execName_cstr; 949 const char *coreName_cstr; 950 jboolean isCopy; 951 struct ps_prochandle* ph; 952 953 execName_cstr = (*env)->GetStringUTFChars(env, execName, &isCopy); 954 CHECK_EXCEPTION; 955 coreName_cstr = (*env)->GetStringUTFChars(env, coreName, &isCopy); 956 CHECK_EXCEPTION; 957 958 print_debug("attach: %s %s\n", execName_cstr, coreName_cstr); 959 960 if ( (ph = Pgrab_core(execName_cstr, coreName_cstr)) == NULL) { 961 (*env)->ReleaseStringUTFChars(env, execName, execName_cstr); 962 (*env)->ReleaseStringUTFChars(env, coreName, coreName_cstr); 963 THROW_NEW_DEBUGGER_EXCEPTION("Can't attach to the core file"); 964 } 965 (*env)->SetLongField(env, this_obj, p_ps_prochandle_ID, (jlong)(intptr_t)ph); 966 (*env)->ReleaseStringUTFChars(env, execName, execName_cstr); 967 (*env)->ReleaseStringUTFChars(env, coreName, coreName_cstr); 968 fillLoadObjects(env, this_obj, ph); 969 } 970 971 static void detach_cleanup(task_t gTask, JNIEnv *env, jobject this_obj, bool throw_exception) { 972 mach_port_deallocate(mach_task_self(), tgt_exception_port); 973 mach_port_deallocate(mach_task_self(), gTask); 974 975 id symbolicator = getSymbolicator(env, this_obj); 976 if (symbolicator != nil) { 977 CFRelease(symbolicator); 978 } 979 if (throw_exception) { 980 THROW_NEW_DEBUGGER_EXCEPTION("Cannot detach."); 981 } 982 } 983 984 /* 985 * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal 986 * Method: detach0 987 * Signature: ()V 988 */ 989 JNIEXPORT void JNICALL 990 Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_detach0( 991 JNIEnv *env, jobject this_obj) 992 { 993 print_debug("detach0 called\n"); 994 struct ps_prochandle* ph = get_proc_handle(env, this_obj); 995 if (ph != NULL && ph->core != NULL) { 996 Prelease(ph); 997 return; 998 } 999 JNF_COCOA_ENTER(env); 1000 1001 task_t gTask = getTask(env, this_obj); 1002 kern_return_t k_res = 0; 1003 1004 // Restore the pre-saved original exception ports registered with the target process 1005 for (uint32_t i = 0; i < exception_saved_state.saved_exception_types_count; ++i) { 1006 k_res = task_set_exception_ports(gTask, 1007 exception_saved_state.saved_masks[i], 1008 exception_saved_state.saved_ports[i], 1009 exception_saved_state.saved_behaviors[i], 1010 exception_saved_state.saved_flavors[i]); 1011 if (k_res != KERN_SUCCESS) { 1012 print_error("detach: task_set_exception_ports failed with %d while " 1013 "restoring the target exception ports.\n", k_res); 1014 detach_cleanup(gTask, env, this_obj, true); 1015 } 1016 } 1017 1018 // detach from the ptraced process causing it to resume execution 1019 int pid; 1020 k_res = pid_for_task(gTask, &pid); 1021 if (k_res != KERN_SUCCESS) { 1022 print_error("detach: pid_for_task(%d) failed (%d)\n", pid, k_res); 1023 detach_cleanup(gTask, env, this_obj, true); 1024 } 1025 else { 1026 errno = 0; 1027 ptrace(PT_DETACH, pid, (caddr_t)1, 0); 1028 if (errno != 0) { 1029 print_error("detach: ptrace(PT_DETACH,...) failed: %s", strerror(errno)); 1030 detach_cleanup(gTask, env, this_obj, true); 1031 } 1032 } 1033 1034 // reply to the previous exception message 1035 k_res = mach_msg(&rep_msg.header, 1036 MACH_SEND_MSG| MACH_SEND_INTERRUPT, 1037 rep_msg.header.msgh_size, 1038 0, 1039 MACH_PORT_NULL, 1040 MACH_MSG_TIMEOUT_NONE, 1041 MACH_PORT_NULL); 1042 if (k_res != MACH_MSG_SUCCESS) { 1043 print_error("detach: mach_msg() for replying to pending exceptions failed: '%s' (%d)\n", 1044 mach_error_string(k_res), k_res); 1045 detach_cleanup(gTask, env, this_obj, true); 1046 } 1047 1048 detach_cleanup(gTask, env, this_obj, false); 1049 1050 JNF_COCOA_EXIT(env); 1051 }