1 /* 2 * Copyright (c) 2002, 2020, 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 if ((*env)->ExceptionOccurred(env)) { 247 if (objectName_cstr != NULL) { 248 (*env)->ReleaseStringUTFChars(env, objectName, objectName_cstr); 249 } 250 return 0; 251 } 252 253 print_debug("look for %s \n", symbolName_cstr); 254 addr = (jlong) lookup_symbol(ph, objectName_cstr, symbolName_cstr); 255 256 if (objectName_cstr != NULL) { 257 (*env)->ReleaseStringUTFChars(env, objectName, objectName_cstr); 258 } 259 (*env)->ReleaseStringUTFChars(env, symbolName, symbolName_cstr); 260 return addr; 261 } 262 263 /* 264 * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal 265 * Method: lookupByName0 266 * Signature: (Ljava/lang/String;Ljava/lang/String;)J 267 */ 268 JNIEXPORT jlong JNICALL 269 Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_lookupByName0( 270 JNIEnv *env, jobject this_obj, 271 jstring objectName, jstring symbolName) 272 { 273 struct ps_prochandle* ph = get_proc_handle(env, this_obj); 274 if (ph != NULL && ph->core != NULL) { 275 return lookupByNameIncore(env, ph, this_obj, objectName, symbolName); 276 } 277 278 jlong address = 0; 279 280 JNF_COCOA_ENTER(env); 281 NSString *symbolNameString = JNFJavaToNSString(env, symbolName); 282 283 print_debug("lookupInProcess called for %s\n", [symbolNameString UTF8String]); 284 285 id symbolicator = getSymbolicator(env, this_obj); 286 if (symbolicator != nil) { 287 uint64_t (*dynamicCall)(id, SEL, NSString *) = (uint64_t (*)(id, SEL, NSString *))&objc_msgSend; 288 address = (jlong) dynamicCall(symbolicator, @selector(addressForSymbol:), symbolNameString); 289 } 290 291 print_debug("address of symbol %s = %llx\n", [symbolNameString UTF8String], address); 292 JNF_COCOA_EXIT(env); 293 294 return address; 295 } 296 297 /* 298 * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal 299 * Method: lookupByAddress0 300 * Signature: (J)Lsun/jvm/hotspot/debugger/cdbg/ClosestSymbol; 301 */ 302 JNIEXPORT jobject JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_lookupByAddress0 303 (JNIEnv *env, jobject this_obj, jlong addr) { 304 uintptr_t offset; 305 const char* sym = NULL; 306 jstring sym_string; 307 308 struct ps_prochandle* ph = get_proc_handle(env, this_obj); 309 if (ph != NULL && ph->core != NULL) { 310 sym = symbol_for_pc(ph, (uintptr_t) addr, &offset); 311 if (sym == NULL) return 0; 312 sym_string = (*env)->NewStringUTF(env, sym); 313 CHECK_EXCEPTION_(0); 314 return (*env)->CallObjectMethod(env, this_obj, createClosestSymbol_ID, 315 sym_string, (jlong)offset); 316 } 317 return 0; 318 } 319 320 /** called from Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_readBytesFromProcess0 */ 321 jbyteArray readBytesFromCore( 322 JNIEnv *env, struct ps_prochandle *ph, jobject this_obj, jlong addr, jlong numBytes) 323 { 324 jboolean isCopy; 325 jbyteArray array; 326 jbyte *bufPtr; 327 ps_err_e err; 328 329 array = (*env)->NewByteArray(env, numBytes); 330 CHECK_EXCEPTION_(0); 331 bufPtr = (*env)->GetByteArrayElements(env, array, &isCopy); 332 CHECK_EXCEPTION_(0); 333 334 err = ps_pread(ph, (psaddr_t) (uintptr_t)addr, bufPtr, numBytes); 335 (*env)->ReleaseByteArrayElements(env, array, bufPtr, 0); 336 return (err == PS_OK)? array : 0; 337 } 338 339 /* 340 * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal 341 * Method: readBytesFromProcess0 342 * Signature: (JJ)Lsun/jvm/hotspot/debugger/ReadResult; 343 */ 344 JNIEXPORT jbyteArray JNICALL 345 Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_readBytesFromProcess0( 346 JNIEnv *env, jobject this_obj, 347 jlong addr, jlong numBytes) 348 { 349 print_debug("readBytesFromProcess called. addr = %llx numBytes = %lld\n", addr, numBytes); 350 351 // must allocate storage instead of using former parameter buf 352 jbyteArray array; 353 354 struct ps_prochandle* ph = get_proc_handle(env, this_obj); 355 if (ph != NULL && ph->core != NULL) { 356 return readBytesFromCore(env, ph, this_obj, addr, numBytes); 357 } 358 359 array = (*env)->NewByteArray(env, numBytes); 360 CHECK_EXCEPTION_(0); 361 362 unsigned long alignedAddress; 363 unsigned long alignedLength = 0; 364 kern_return_t result; 365 vm_offset_t *pages; 366 int *mapped; 367 long pageCount; 368 uint byteCount; 369 int i; 370 unsigned long remaining; 371 372 alignedAddress = trunc_page(addr); 373 if (addr != alignedAddress) { 374 alignedLength += addr - alignedAddress; 375 } 376 alignedLength = round_page(numBytes); 377 pageCount = alignedLength/vm_page_size; 378 379 // Allocate storage for pages and flags. 380 pages = malloc(pageCount * sizeof(vm_offset_t)); 381 if (pages == NULL) { 382 (*env)->DeleteLocalRef(env, array); 383 return NULL; 384 } 385 mapped = calloc(pageCount, sizeof(int)); 386 if (mapped == NULL) { 387 (*env)->DeleteLocalRef(env, array); 388 free(pages); 389 return NULL; 390 } 391 392 task_t gTask = getTask(env, this_obj); 393 // Try to read each of the pages. 394 for (i = 0; i < pageCount; i++) { 395 result = vm_read(gTask, alignedAddress + i*vm_page_size, vm_page_size, 396 &pages[i], &byteCount); 397 mapped[i] = (result == KERN_SUCCESS); 398 // assume all failures are unmapped pages 399 } 400 401 print_debug("%ld pages\n", pageCount); 402 403 remaining = numBytes; 404 405 for (i = 0; i < pageCount; i++) { 406 unsigned long len = vm_page_size; 407 unsigned long start = 0; 408 409 if (i == 0) { 410 start = addr - alignedAddress; 411 len = vm_page_size - start; 412 } 413 414 if (i == (pageCount - 1)) { 415 len = remaining; 416 } 417 418 if (mapped[i]) { 419 print_debug("page %d mapped (len %ld start %ld)\n", i, len, start); 420 (*env)->SetByteArrayRegion(env, array, 0, len, ((jbyte *) pages[i] + start)); 421 vm_deallocate(mach_task_self(), pages[i], vm_page_size); 422 } 423 424 remaining -= len; 425 } 426 427 free (pages); 428 free (mapped); 429 return array; 430 } 431 432 /** Only used for core file reading, set thread_id for threads which is got after core file parsed. 433 * Thread context is available in Mach-O core file but thread id is not. We can get thread id 434 * from Threads which store all java threads information when they are created. Here we can identify 435 * them as java threads by checking if a thread's rsp or rbp within a java thread's stack. 436 * Note Macosx uses unique_thread_id which is different from other platforms though printed ids 437 * are still pthread id. Function BsdDebuggerLocal.getJavaThreadsInfo returns an array of long 438 * integers to host all java threads' id, stack_start, stack_end as: 439 * [uid0, stack_start0, stack_end0, uid1, stack_start1, stack_end1, ...] 440 * 441 * The work cannot be done at init0 since Threads is not available yet(VM not initialized yet). 442 * This function should be called only once if succeeded 443 */ 444 bool fill_java_threads(JNIEnv* env, jobject this_obj, struct ps_prochandle* ph) { 445 int n = 0, i = 0, j; 446 struct reg regs; 447 448 jlongArray thrinfos = (*env)->CallObjectMethod(env, this_obj, getJavaThreadsInfo_ID); 449 CHECK_EXCEPTION_(false); 450 int len = (int)(*env)->GetArrayLength(env, thrinfos); 451 uint64_t* cinfos = (uint64_t *)(*env)->GetLongArrayElements(env, thrinfos, NULL); 452 CHECK_EXCEPTION_(false); 453 n = get_num_threads(ph); 454 print_debug("fill_java_threads called, num_of_thread = %d\n", n); 455 for (i = 0; i < n; i++) { 456 if (!get_nth_lwp_regs(ph, i, ®s)) { 457 print_debug("Could not get regs of thread %d, already set!\n", i); 458 (*env)->ReleaseLongArrayElements(env, thrinfos, (jlong*)cinfos, 0); 459 return false; 460 } 461 for (j = 0; j < len; j += 3) { 462 lwpid_t uid = cinfos[j]; 463 uint64_t beg = cinfos[j + 1]; 464 uint64_t end = cinfos[j + 2]; 465 if ((regs.r_rsp < end && regs.r_rsp >= beg) || 466 (regs.r_rbp < end && regs.r_rbp >= beg)) { 467 set_lwp_id(ph, i, uid); 468 break; 469 } 470 } 471 } 472 (*env)->ReleaseLongArrayElements(env, thrinfos, (jlong*)cinfos, 0); 473 CHECK_EXCEPTION_(false); 474 return true; 475 } 476 477 /* For core file only, called from 478 * Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_getThreadIntegerRegisterSet0 479 */ 480 jlongArray getThreadIntegerRegisterSetFromCore(JNIEnv *env, jobject this_obj, long lwp_id, struct ps_prochandle* ph) { 481 if (!_threads_filled) { 482 if (!fill_java_threads(env, this_obj, ph)) { 483 throw_new_debugger_exception(env, "Failed to fill in threads"); 484 return 0; 485 } else { 486 _threads_filled = true; 487 } 488 } 489 490 struct reg gregs; 491 jboolean isCopy; 492 jlongArray array; 493 jlong *regs; 494 495 if (get_lwp_regs(ph, lwp_id, &gregs) != true) { 496 THROW_NEW_DEBUGGER_EXCEPTION_("get_thread_regs failed for a lwp", 0); 497 } 498 499 #undef NPRGREG 500 #undef REG_INDEX 501 #if amd64 502 #define NPRGREG sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_NPRGREG 503 #define REG_INDEX(reg) sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_##reg 504 505 array = (*env)->NewLongArray(env, NPRGREG); 506 CHECK_EXCEPTION_(0); 507 regs = (*env)->GetLongArrayElements(env, array, &isCopy); 508 509 regs[REG_INDEX(R15)] = gregs.r_r15; 510 regs[REG_INDEX(R14)] = gregs.r_r14; 511 regs[REG_INDEX(R13)] = gregs.r_r13; 512 regs[REG_INDEX(R12)] = gregs.r_r12; 513 regs[REG_INDEX(RBP)] = gregs.r_rbp; 514 regs[REG_INDEX(RBX)] = gregs.r_rbx; 515 regs[REG_INDEX(R11)] = gregs.r_r11; 516 regs[REG_INDEX(R10)] = gregs.r_r10; 517 regs[REG_INDEX(R9)] = gregs.r_r9; 518 regs[REG_INDEX(R8)] = gregs.r_r8; 519 regs[REG_INDEX(RAX)] = gregs.r_rax; 520 regs[REG_INDEX(RCX)] = gregs.r_rcx; 521 regs[REG_INDEX(RDX)] = gregs.r_rdx; 522 regs[REG_INDEX(RSI)] = gregs.r_rsi; 523 regs[REG_INDEX(RDI)] = gregs.r_rdi; 524 regs[REG_INDEX(RIP)] = gregs.r_rip; 525 regs[REG_INDEX(CS)] = gregs.r_cs; 526 regs[REG_INDEX(RSP)] = gregs.r_rsp; 527 regs[REG_INDEX(SS)] = gregs.r_ss; 528 regs[REG_INDEX(FSBASE)] = 0; 529 regs[REG_INDEX(GSBASE)] = 0; 530 regs[REG_INDEX(DS)] = gregs.r_ds; 531 regs[REG_INDEX(ES)] = gregs.r_es; 532 regs[REG_INDEX(FS)] = gregs.r_fs; 533 regs[REG_INDEX(GS)] = gregs.r_gs; 534 regs[REG_INDEX(TRAPNO)] = gregs.r_trapno; 535 regs[REG_INDEX(RFL)] = gregs.r_rflags; 536 537 (*env)->ReleaseLongArrayElements(env, array, regs, JNI_COMMIT); 538 #endif /* amd64 */ 539 return array; 540 } 541 542 /* 543 * Lookup the thread_t that corresponds to the given thread_id. 544 * The thread_id should be the result from calling thread_info() with THREAD_IDENTIFIER_INFO 545 * and reading the m_ident_info.thread_id returned. 546 * The returned thread_t is the mach send right to the kernel port for the corresponding thread. 547 * 548 * We cannot simply use the OSThread._thread_id field in the JVM. This is set to ::mach_thread_self() 549 * in the VM, but that thread port is not valid for a remote debugger to access the thread. 550 */ 551 thread_t 552 lookupThreadFromThreadId(task_t task, jlong thread_id) { 553 print_debug("lookupThreadFromThreadId thread_id=0x%llx\n", thread_id); 554 555 thread_array_t thread_list = NULL; 556 mach_msg_type_number_t thread_list_count = 0; 557 thread_t result_thread = 0; 558 int i; 559 560 // get the list of all the send rights 561 kern_return_t result = task_threads(task, &thread_list, &thread_list_count); 562 if (result != KERN_SUCCESS) { 563 print_debug("task_threads returned 0x%x\n", result); 564 return 0; 565 } 566 567 for(i = 0 ; i < thread_list_count; i++) { 568 thread_identifier_info_data_t m_ident_info; 569 mach_msg_type_number_t count = THREAD_IDENTIFIER_INFO_COUNT; 570 571 // get the THREAD_IDENTIFIER_INFO for the send right 572 result = thread_info(thread_list[i], THREAD_IDENTIFIER_INFO, (thread_info_t) &m_ident_info, &count); 573 if (result != KERN_SUCCESS) { 574 print_debug("thread_info returned 0x%x\n", result); 575 break; 576 } 577 578 // if this is the one we're looking for, return the send right 579 if (thread_id == m_ident_info.thread_id) 580 { 581 result_thread = thread_list[i]; 582 break; 583 } 584 } 585 586 vm_size_t thread_list_size = (vm_size_t) (thread_list_count * sizeof (thread_t)); 587 vm_deallocate(mach_task_self(), (vm_address_t) thread_list, thread_list_count); 588 589 return result_thread; 590 } 591 592 593 /* 594 * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal 595 * Method: getThreadIntegerRegisterSet0 596 * Signature: (J)[J 597 */ 598 JNIEXPORT jlongArray JNICALL 599 Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_getThreadIntegerRegisterSet0( 600 JNIEnv *env, jobject this_obj, 601 jlong thread_id) 602 { 603 print_debug("getThreadIntegerRegisterSet0 called\n"); 604 605 struct ps_prochandle* ph = get_proc_handle(env, this_obj); 606 if (ph != NULL && ph->core != NULL) { 607 return getThreadIntegerRegisterSetFromCore(env, this_obj, thread_id, ph); 608 } 609 610 kern_return_t result; 611 thread_t tid; 612 mach_msg_type_number_t count = HSDB_THREAD_STATE_COUNT; 613 hsdb_thread_state_t state; 614 jlongArray registerArray; 615 jlong *primitiveArray; 616 task_t gTask = getTask(env, this_obj); 617 618 tid = lookupThreadFromThreadId(gTask, thread_id); 619 620 result = thread_get_state(tid, HSDB_THREAD_STATE, (thread_state_t)&state, &count); 621 622 if (result != KERN_SUCCESS) { 623 // This is not considered fatal. Unlike on Linux and Windows, we haven't seen a 624 // failure to get thread registers, but if it were to fail the response should 625 // be the same. By ignoring this error and returning NULL, stacking walking code 626 // will get null registers and fallback to using the "last java frame" if setup. 627 fprintf(stdout, "WARNING: getThreadIntegerRegisterSet0: thread_get_state failed (%d) for thread (%d)\n", 628 result, tid); 629 fflush(stdout); 630 return NULL; 631 } 632 633 #if amd64 634 #define NPRGREG sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_NPRGREG 635 #undef REG_INDEX 636 #define REG_INDEX(reg) sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_##reg 637 638 // 64 bit 639 print_debug("Getting threads for a 64-bit process\n"); 640 registerArray = (*env)->NewLongArray(env, NPRGREG); 641 CHECK_EXCEPTION_(0); 642 primitiveArray = (*env)->GetLongArrayElements(env, registerArray, NULL); 643 644 primitiveArray[REG_INDEX(R15)] = state.__r15; 645 primitiveArray[REG_INDEX(R14)] = state.__r14; 646 primitiveArray[REG_INDEX(R13)] = state.__r13; 647 primitiveArray[REG_INDEX(R12)] = state.__r12; 648 primitiveArray[REG_INDEX(R11)] = state.__r11; 649 primitiveArray[REG_INDEX(R10)] = state.__r10; 650 primitiveArray[REG_INDEX(R9)] = state.__r9; 651 primitiveArray[REG_INDEX(R8)] = state.__r8; 652 primitiveArray[REG_INDEX(RDI)] = state.__rdi; 653 primitiveArray[REG_INDEX(RSI)] = state.__rsi; 654 primitiveArray[REG_INDEX(RBP)] = state.__rbp; 655 primitiveArray[REG_INDEX(RBX)] = state.__rbx; 656 primitiveArray[REG_INDEX(RDX)] = state.__rdx; 657 primitiveArray[REG_INDEX(RCX)] = state.__rcx; 658 primitiveArray[REG_INDEX(RAX)] = state.__rax; 659 primitiveArray[REG_INDEX(TRAPNO)] = 0; // trapno, not used 660 primitiveArray[REG_INDEX(ERR)] = 0; // err, not used 661 primitiveArray[REG_INDEX(RIP)] = state.__rip; 662 primitiveArray[REG_INDEX(CS)] = state.__cs; 663 primitiveArray[REG_INDEX(RFL)] = state.__rflags; 664 primitiveArray[REG_INDEX(RSP)] = state.__rsp; 665 primitiveArray[REG_INDEX(SS)] = 0; // We don't have SS 666 primitiveArray[REG_INDEX(FS)] = state.__fs; 667 primitiveArray[REG_INDEX(GS)] = state.__gs; 668 primitiveArray[REG_INDEX(ES)] = 0; 669 primitiveArray[REG_INDEX(DS)] = 0; 670 primitiveArray[REG_INDEX(FSBASE)] = 0; 671 primitiveArray[REG_INDEX(GSBASE)] = 0; 672 print_debug("set registers\n"); 673 674 (*env)->ReleaseLongArrayElements(env, registerArray, primitiveArray, 0); 675 676 #else 677 #error UNSUPPORTED_ARCH 678 #endif /* amd64 */ 679 680 return registerArray; 681 } 682 683 /* 684 * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal 685 * Method: translateTID0 686 * Signature: (I)I 687 */ 688 JNIEXPORT jint JNICALL 689 Java_sun_jvm_hotspot_debugger_macosx_MacOSXDebuggerLocal_translateTID0( 690 JNIEnv *env, jobject this_obj, jint tid) 691 { 692 print_debug("translateTID0 called on tid = 0x%x\n", (int)tid); 693 694 kern_return_t result; 695 thread_t foreign_tid, usable_tid; 696 mach_msg_type_name_t type; 697 698 foreign_tid = tid; 699 700 task_t gTask = getTask(env, this_obj); 701 result = mach_port_extract_right(gTask, foreign_tid, 702 MACH_MSG_TYPE_COPY_SEND, 703 &usable_tid, &type); 704 if (result != KERN_SUCCESS) 705 return -1; 706 707 print_debug("translateTID0: 0x%x -> 0x%x\n", foreign_tid, usable_tid); 708 709 return (jint) usable_tid; 710 } 711 712 // attach to a process/thread specified by "pid" 713 static bool ptrace_attach(pid_t pid) { 714 errno = 0; 715 ptrace(PT_ATTACHEXC, pid, 0, 0); 716 717 if (errno != 0) { 718 print_error("ptrace_attach: ptrace(PT_ATTACHEXC,...) failed: %s", strerror(errno)); 719 return false; 720 } 721 return true; 722 } 723 724 kern_return_t catch_mach_exception_raise( 725 mach_port_t exception_port, mach_port_t thread_port, mach_port_t task_port, 726 exception_type_t exception_type, mach_exception_data_t codes, 727 mach_msg_type_number_t num_codes) { 728 729 print_debug("catch_mach_exception_raise: Exception port = %d thread_port = %d " 730 "task port %d exc type = %d num_codes %d\n", 731 exception_port, thread_port, task_port, exception_type, num_codes); 732 733 // This message should denote a Unix soft signal, with 734 // 1. the exception type = EXC_SOFTWARE 735 // 2. codes[0] (which is the code) = EXC_SOFT_SIGNAL 736 // 3. codes[1] (which is the sub-code) = SIGSTOP 737 if (!(exception_type == EXC_SOFTWARE && 738 codes[0] == EXC_SOFT_SIGNAL && 739 codes[num_codes -1] == SIGSTOP)) { 740 print_error("catch_mach_exception_raise: Message doesn't denote a Unix " 741 "soft signal. exception_type = %d, codes[0] = %d, " 742 "codes[num_codes -1] = %d, num_codes = %d\n", 743 exception_type, codes[0], codes[num_codes - 1], num_codes); 744 return MACH_RCV_INVALID_TYPE; 745 } 746 return KERN_SUCCESS; 747 } 748 749 kern_return_t catch_mach_exception_raise_state( 750 mach_port_t exception_port, exception_type_t exception, const mach_exception_data_t code, 751 mach_msg_type_number_t code_cnt, int *flavor, const thread_state_t old_state, 752 mach_msg_type_number_t old_state_cnt, thread_state_t new_state, 753 mach_msg_type_number_t *new_state_cnt) { 754 return MACH_RCV_INVALID_TYPE; 755 } 756 757 758 kern_return_t catch_mach_exception_raise_state_identity( 759 mach_port_t exception_port, mach_port_t thread, mach_port_t task, 760 exception_type_t exception, mach_exception_data_t code, 761 mach_msg_type_number_t code_cnt, int *flavor, 762 thread_state_t old_state, mach_msg_type_number_t old_state_cnt, 763 thread_state_t new_state, mach_msg_type_number_t *new_state_cnt) { 764 return MACH_RCV_INVALID_TYPE; 765 } 766 767 // wait to receive an exception message 768 static bool wait_for_exception() { 769 kern_return_t result; 770 771 result = mach_msg(&exc_msg.header, 772 MACH_RCV_MSG, 773 0, 774 sizeof(exc_msg), 775 tgt_exception_port, 776 MACH_MSG_TIMEOUT_NONE, 777 MACH_PORT_NULL); 778 779 if (result != MACH_MSG_SUCCESS) { 780 print_error("attach: wait_for_exception: mach_msg() failed: '%s' (%d)\n", 781 mach_error_string(result), result); 782 return false; 783 } 784 785 if (mach_exc_server(&exc_msg.header, &rep_msg.header) == false || 786 rep_msg.ret_code != KERN_SUCCESS) { 787 print_error("attach: wait_for_exception: mach_exc_server failure\n"); 788 if (rep_msg.ret_code != KERN_SUCCESS) { 789 print_error("catch_mach_exception_raise() failed '%s' (%d)\n", 790 mach_error_string(rep_msg.ret_code), rep_msg.ret_code); 791 } 792 return false; 793 } 794 795 print_debug("reply msg from mach_exc_server: (msg->{bits = %#x, size = %u, " 796 "remote_port = %#x, local_port = %#x, reserved = 0x%x, id = 0x%x},)", 797 rep_msg.header.msgh_bits, rep_msg.header.msgh_size, 798 rep_msg.header.msgh_remote_port, rep_msg.header.msgh_local_port, 799 rep_msg.header.msgh_reserved, rep_msg.header.msgh_id); 800 801 return true; 802 } 803 804 /* 805 * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal 806 * Method: attach0 807 * Signature: (I)V 808 */ 809 JNIEXPORT void JNICALL 810 Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_attach0__I( 811 JNIEnv *env, jobject this_obj, jint jpid) 812 { 813 print_debug("attach0 called for jpid=%d\n", (int)jpid); 814 815 JNF_COCOA_ENTER(env); 816 817 kern_return_t result; 818 task_t gTask = 0; 819 820 result = task_for_pid(mach_task_self(), jpid, &gTask); 821 if (result != KERN_SUCCESS) { 822 print_error("attach: task_for_pid(%d) failed: '%s' (%d)\n", (int)jpid, mach_error_string(result), result); 823 THROW_NEW_DEBUGGER_EXCEPTION( 824 "Can't attach to the process. Could be caused by an incorrect pid or lack of privileges."); 825 } 826 putTask(env, this_obj, gTask); 827 828 // Allocate an exception port. 829 result = mach_port_allocate(mach_task_self(), 830 MACH_PORT_RIGHT_RECEIVE, 831 &tgt_exception_port); 832 if (result != KERN_SUCCESS) { 833 print_error("attach: mach_port_allocate() for tgt_exception_port failed: '%s' (%d)\n", 834 mach_error_string(result), result); 835 THROW_NEW_DEBUGGER_EXCEPTION( 836 "Can't attach to the process. Couldn't allocate an exception port."); 837 } 838 839 // Enable the new exception port to send messages. 840 result = mach_port_insert_right (mach_task_self(), 841 tgt_exception_port, 842 tgt_exception_port, 843 MACH_MSG_TYPE_MAKE_SEND); 844 if (result != KERN_SUCCESS) { 845 print_error("attach: mach_port_insert_right() failed for port 0x%x: '%s' (%d)\n", 846 tgt_exception_port, mach_error_string(result), result); 847 THROW_NEW_DEBUGGER_EXCEPTION( 848 "Can't attach to the process. Couldn't add send privileges to the exception port."); 849 } 850 851 // Save the existing original exception ports registered with the target 852 // process (for later restoration while detaching from the process). 853 result = task_get_exception_ports(gTask, 854 EXC_MASK_ALL, 855 exception_saved_state.saved_masks, 856 &exception_saved_state.saved_exception_types_count, 857 exception_saved_state.saved_ports, 858 exception_saved_state.saved_behaviors, 859 exception_saved_state.saved_flavors); 860 861 if (result != KERN_SUCCESS) { 862 print_error("attach: task_get_exception_ports() failed: '%s' (%d)\n", 863 mach_error_string(result), result); 864 THROW_NEW_DEBUGGER_EXCEPTION( 865 "Can't attach to the process. Could not get the target exception ports."); 866 } 867 868 // register the exception port to be used for all future exceptions with the 869 // target process. 870 result = task_set_exception_ports(gTask, 871 EXC_MASK_ALL, 872 tgt_exception_port, 873 EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES, 874 THREAD_STATE_NONE); 875 876 if (result != KERN_SUCCESS) { 877 print_error("attach: task_set_exception_ports() failed -- port 0x%x: '%s' (%d)\n", 878 tgt_exception_port, mach_error_string(result), result); 879 mach_port_deallocate(mach_task_self(), gTask); 880 mach_port_deallocate(mach_task_self(), tgt_exception_port); 881 THROW_NEW_DEBUGGER_EXCEPTION( 882 "Can't attach to the process. Could not register the exception port " 883 "with the target process."); 884 } 885 886 // use ptrace to stop the process 887 // on os x, ptrace only needs to be called on the process, not the individual threads 888 if (ptrace_attach(jpid) != true) { 889 print_error("attach: ptrace failure in attaching to %d\n", (int)jpid); 890 mach_port_deallocate(mach_task_self(), gTask); 891 mach_port_deallocate(mach_task_self(), tgt_exception_port); 892 THROW_NEW_DEBUGGER_EXCEPTION("Can't ptrace attach to the process"); 893 } 894 895 if (wait_for_exception() != true) { 896 mach_port_deallocate(mach_task_self(), gTask); 897 mach_port_deallocate(mach_task_self(), tgt_exception_port); 898 THROW_NEW_DEBUGGER_EXCEPTION( 899 "Can't attach to the process. Issues with reception of the exception message."); 900 } 901 902 // suspend all the threads in the task 903 result = task_suspend(gTask); 904 if (result != KERN_SUCCESS) { 905 print_error("attach: task_suspend() failed: '%s' (%d)\n", 906 mach_error_string(result), result); 907 mach_port_deallocate(mach_task_self(), gTask); 908 mach_port_deallocate(mach_task_self(), tgt_exception_port); 909 THROW_NEW_DEBUGGER_EXCEPTION("Can't attach. Unable to suspend all the threads in the task."); 910 } 911 912 id symbolicator = nil; 913 id jrsSymbolicator = objc_lookUpClass("JRSSymbolicator"); 914 if (jrsSymbolicator != nil) { 915 id (*dynamicCall)(id, SEL, pid_t) = (id (*)(id, SEL, pid_t))&objc_msgSend; 916 symbolicator = dynamicCall(jrsSymbolicator, @selector(symbolicatorForPid:), (pid_t)jpid); 917 } 918 if (symbolicator != nil) { 919 CFRetain(symbolicator); // pin symbolicator while in java heap 920 } 921 922 putSymbolicator(env, this_obj, symbolicator); 923 if (symbolicator == nil) { 924 mach_port_deallocate(mach_task_self(), gTask); 925 mach_port_deallocate(mach_task_self(), tgt_exception_port); 926 THROW_NEW_DEBUGGER_EXCEPTION("Can't attach symbolicator to the process"); 927 } 928 929 JNF_COCOA_EXIT(env); 930 } 931 932 /** For core file, 933 called from Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_attach0__Ljava_lang_String_2Ljava_lang_String_2 */ 934 static void fillLoadObjects(JNIEnv* env, jobject this_obj, struct ps_prochandle* ph) { 935 int n = 0, i = 0; 936 937 // add load objects 938 n = get_num_libs(ph); 939 for (i = 0; i < n; i++) { 940 uintptr_t base; 941 const char* name; 942 jobject loadObject; 943 jobject loadObjectList; 944 jstring nameString; 945 946 base = get_lib_base(ph, i); 947 name = get_lib_name(ph, i); 948 nameString = (*env)->NewStringUTF(env, name); 949 CHECK_EXCEPTION; 950 loadObject = (*env)->CallObjectMethod(env, this_obj, createLoadObject_ID, 951 nameString, (jlong)0, (jlong)base); 952 CHECK_EXCEPTION; 953 loadObjectList = (*env)->GetObjectField(env, this_obj, loadObjectList_ID); 954 CHECK_EXCEPTION; 955 (*env)->CallBooleanMethod(env, loadObjectList, listAdd_ID, loadObject); 956 CHECK_EXCEPTION; 957 } 958 } 959 960 /* 961 * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal 962 * Method: attach0 963 * Signature: (Ljava/lang/String;Ljava/lang/String;)V 964 */ 965 JNIEXPORT void JNICALL 966 Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_attach0__Ljava_lang_String_2Ljava_lang_String_2( 967 JNIEnv *env, jobject this_obj, jstring execName, jstring coreName) 968 { 969 const char *execName_cstr; 970 const char *coreName_cstr; 971 jboolean isCopy; 972 struct ps_prochandle* ph; 973 974 execName_cstr = (*env)->GetStringUTFChars(env, execName, &isCopy); 975 CHECK_EXCEPTION; 976 coreName_cstr = (*env)->GetStringUTFChars(env, coreName, &isCopy); 977 if ((*env)->ExceptionOccurred(env)) { 978 (*env)->ReleaseStringUTFChars(env, execName, execName_cstr); 979 return; 980 } 981 982 print_debug("attach: %s %s\n", execName_cstr, coreName_cstr); 983 984 if ( (ph = Pgrab_core(execName_cstr, coreName_cstr)) == NULL) { 985 (*env)->ReleaseStringUTFChars(env, execName, execName_cstr); 986 (*env)->ReleaseStringUTFChars(env, coreName, coreName_cstr); 987 THROW_NEW_DEBUGGER_EXCEPTION("Can't attach to the core file"); 988 } 989 (*env)->SetLongField(env, this_obj, p_ps_prochandle_ID, (jlong)(intptr_t)ph); 990 (*env)->ReleaseStringUTFChars(env, execName, execName_cstr); 991 (*env)->ReleaseStringUTFChars(env, coreName, coreName_cstr); 992 fillLoadObjects(env, this_obj, ph); 993 } 994 995 static void detach_cleanup(task_t gTask, JNIEnv *env, jobject this_obj, bool throw_exception) { 996 mach_port_deallocate(mach_task_self(), tgt_exception_port); 997 mach_port_deallocate(mach_task_self(), gTask); 998 999 id symbolicator = getSymbolicator(env, this_obj); 1000 if (symbolicator != nil) { 1001 CFRelease(symbolicator); 1002 } 1003 if (throw_exception) { 1004 THROW_NEW_DEBUGGER_EXCEPTION("Cannot detach."); 1005 } 1006 } 1007 1008 /* 1009 * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal 1010 * Method: detach0 1011 * Signature: ()V 1012 */ 1013 JNIEXPORT void JNICALL 1014 Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_detach0( 1015 JNIEnv *env, jobject this_obj) 1016 { 1017 print_debug("detach0 called\n"); 1018 struct ps_prochandle* ph = get_proc_handle(env, this_obj); 1019 if (ph != NULL && ph->core != NULL) { 1020 Prelease(ph); 1021 return; 1022 } 1023 JNF_COCOA_ENTER(env); 1024 1025 task_t gTask = getTask(env, this_obj); 1026 kern_return_t k_res = 0; 1027 1028 // Restore the pre-saved original exception ports registered with the target process 1029 for (uint32_t i = 0; i < exception_saved_state.saved_exception_types_count; ++i) { 1030 k_res = task_set_exception_ports(gTask, 1031 exception_saved_state.saved_masks[i], 1032 exception_saved_state.saved_ports[i], 1033 exception_saved_state.saved_behaviors[i], 1034 exception_saved_state.saved_flavors[i]); 1035 if (k_res != KERN_SUCCESS) { 1036 print_error("detach: task_set_exception_ports failed with %d while " 1037 "restoring the target exception ports.\n", k_res); 1038 detach_cleanup(gTask, env, this_obj, true); 1039 } 1040 } 1041 1042 // detach from the ptraced process causing it to resume execution 1043 int pid; 1044 k_res = pid_for_task(gTask, &pid); 1045 if (k_res != KERN_SUCCESS) { 1046 print_error("detach: pid_for_task(%d) failed (%d)\n", pid, k_res); 1047 detach_cleanup(gTask, env, this_obj, true); 1048 } 1049 else { 1050 errno = 0; 1051 ptrace(PT_DETACH, pid, (caddr_t)1, 0); 1052 if (errno != 0) { 1053 print_error("detach: ptrace(PT_DETACH,...) failed: %s", strerror(errno)); 1054 detach_cleanup(gTask, env, this_obj, true); 1055 } 1056 } 1057 1058 // reply to the previous exception message 1059 k_res = mach_msg(&rep_msg.header, 1060 MACH_SEND_MSG| MACH_SEND_INTERRUPT, 1061 rep_msg.header.msgh_size, 1062 0, 1063 MACH_PORT_NULL, 1064 MACH_MSG_TIMEOUT_NONE, 1065 MACH_PORT_NULL); 1066 if (k_res != MACH_MSG_SUCCESS) { 1067 print_error("detach: mach_msg() for replying to pending exceptions failed: '%s' (%d)\n", 1068 mach_error_string(k_res), k_res); 1069 detach_cleanup(gTask, env, this_obj, true); 1070 } 1071 1072 detach_cleanup(gTask, env, this_obj, false); 1073 1074 JNF_COCOA_EXIT(env); 1075 }