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 "salibproc.h" 26 #include "sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal.h" 27 #ifndef SOLARIS_11_B159_OR_LATER 28 #include <sys/utsname.h> 29 #endif 30 #include <thread_db.h> 31 #include <strings.h> 32 #include <limits.h> 33 #include <demangle.h> 34 #include <stdarg.h> 35 #include <stdlib.h> 36 #include <errno.h> 37 38 #define CHECK_EXCEPTION_(value) if(env->ExceptionOccurred()) { return value; } 39 #define CHECK_EXCEPTION if(env->ExceptionOccurred()) { return;} 40 #define THROW_NEW_DEBUGGER_EXCEPTION_(str, value) { throwNewDebuggerException(env, str); return value; } 41 #define THROW_NEW_DEBUGGER_EXCEPTION(str) { throwNewDebuggerException(env, str); return;} 42 43 #define SYMBOL_BUF_SIZE 256 44 #define ERR_MSG_SIZE (PATH_MAX + 256) 45 46 // debug modes 47 static int _libsaproc_debug = 0; 48 #ifndef SOLARIS_11_B159_OR_LATER 49 static bool _Pstack_iter_debug = false; 50 51 static void dprintf_2(const char* format,...) { 52 if (_Pstack_iter_debug) { 53 va_list alist; 54 55 va_start(alist, format); 56 fputs("Pstack_iter DEBUG: ", stderr); 57 vfprintf(stderr, format, alist); 58 va_end(alist); 59 } 60 } 61 #endif // !SOLARIS_11_B159_OR_LATER 62 63 static void print_debug(const char* format,...) { 64 if (_libsaproc_debug) { 65 va_list alist; 66 67 va_start(alist, format); 68 fputs("libsaproc DEBUG: ", stderr); 69 vfprintf(stderr, format, alist); 70 va_end(alist); 71 } 72 } 73 74 struct Debugger { 75 JNIEnv* env; 76 jobject this_obj; 77 }; 78 79 struct DebuggerWithObject : Debugger { 80 jobject obj; 81 }; 82 83 struct DebuggerWith2Objects : DebuggerWithObject { 84 jobject obj2; 85 }; 86 87 /* 88 * Portions of user thread level detail gathering code is from pstack source 89 * code. See pstack.c in Solaris 2.8 user commands source code. 90 */ 91 92 static void throwNewDebuggerException(JNIEnv* env, const char* errMsg) { 93 env->ThrowNew(env->FindClass("sun/jvm/hotspot/debugger/DebuggerException"), errMsg); 94 } 95 96 // JNI ids for some fields, methods 97 98 // libproc handler pointer 99 static jfieldID p_ps_prochandle_ID = 0; 100 101 // libthread.so dlopen handle, thread agent ptr and function pointers 102 static jfieldID libthread_db_handle_ID = 0; 103 static jfieldID p_td_thragent_t_ID = 0; 104 static jfieldID p_td_init_ID = 0; 105 static jfieldID p_td_ta_new_ID = 0; 106 static jfieldID p_td_ta_delete_ID = 0; 107 static jfieldID p_td_ta_thr_iter_ID = 0; 108 static jfieldID p_td_thr_get_info_ID = 0; 109 static jfieldID p_td_ta_map_id2thr_ID = 0; 110 static jfieldID p_td_thr_getgregs_ID = 0; 111 112 // reg index fields 113 static jfieldID pcRegIndex_ID = 0; 114 static jfieldID fpRegIndex_ID = 0; 115 116 // part of the class sharing workaround 117 static jfieldID classes_jsa_fd_ID = 0; 118 static jfieldID p_file_map_header_ID = 0; 119 120 // method ids 121 122 static jmethodID getThreadForThreadId_ID = 0; 123 static jmethodID createSenderFrame_ID = 0; 124 static jmethodID createLoadObject_ID = 0; 125 static jmethodID createClosestSymbol_ID = 0; 126 static jmethodID listAdd_ID = 0; 127 128 /* 129 * Functions we need from libthread_db 130 */ 131 typedef td_err_e 132 (*p_td_init_t)(void); 133 typedef td_err_e 134 (*p_td_ta_new_t)(void *, td_thragent_t **); 135 typedef td_err_e 136 (*p_td_ta_delete_t)(td_thragent_t *); 137 typedef td_err_e 138 (*p_td_ta_thr_iter_t)(const td_thragent_t *, td_thr_iter_f *, void *, 139 td_thr_state_e, int, sigset_t *, unsigned); 140 typedef td_err_e 141 (*p_td_thr_get_info_t)(const td_thrhandle_t *, td_thrinfo_t *); 142 typedef td_err_e 143 (*p_td_ta_map_id2thr_t)(const td_thragent_t *, thread_t, td_thrhandle_t *); 144 typedef td_err_e 145 (*p_td_thr_getgregs_t)(const td_thrhandle_t *, prgregset_t); 146 147 static void 148 clear_libthread_db_ptrs(JNIEnv* env, jobject this_obj) { 149 // release libthread_db agent, if we had created 150 p_td_ta_delete_t p_td_ta_delete = 0; 151 p_td_ta_delete = (p_td_ta_delete_t) env->GetLongField(this_obj, p_td_ta_delete_ID); 152 153 td_thragent_t *p_td_thragent_t = 0; 154 p_td_thragent_t = (td_thragent_t*) env->GetLongField(this_obj, p_td_thragent_t_ID); 155 if (p_td_thragent_t != 0 && p_td_ta_delete != 0) { 156 p_td_ta_delete(p_td_thragent_t); 157 } 158 159 // dlclose libthread_db.so 160 void* libthread_db_handle = (void*) env->GetLongField(this_obj, libthread_db_handle_ID); 161 if (libthread_db_handle != 0) { 162 dlclose(libthread_db_handle); 163 } 164 165 env->SetLongField(this_obj, libthread_db_handle_ID, (jlong)0); 166 env->SetLongField(this_obj, p_td_init_ID, (jlong)0); 167 env->SetLongField(this_obj, p_td_ta_new_ID, (jlong)0); 168 env->SetLongField(this_obj, p_td_ta_delete_ID, (jlong)0); 169 env->SetLongField(this_obj, p_td_ta_thr_iter_ID, (jlong)0); 170 env->SetLongField(this_obj, p_td_thr_get_info_ID, (jlong)0); 171 env->SetLongField(this_obj, p_td_ta_map_id2thr_ID, (jlong)0); 172 env->SetLongField(this_obj, p_td_thr_getgregs_ID, (jlong)0); 173 } 174 175 176 static void detach_internal(JNIEnv* env, jobject this_obj) { 177 // clear libthread_db stuff 178 clear_libthread_db_ptrs(env, this_obj); 179 180 // release ptr to ps_prochandle 181 jlong p_ps_prochandle; 182 p_ps_prochandle = env->GetLongField(this_obj, p_ps_prochandle_ID); 183 if (p_ps_prochandle != 0L) { 184 Prelease((struct ps_prochandle*) p_ps_prochandle, PRELEASE_CLEAR); 185 } 186 187 // part of the class sharing workaround 188 int classes_jsa_fd = env->GetIntField(this_obj, classes_jsa_fd_ID); 189 if (classes_jsa_fd != -1) { 190 close(classes_jsa_fd); 191 struct FileMapHeader* pheader = (struct FileMapHeader*) env->GetLongField(this_obj, p_file_map_header_ID); 192 if (pheader != NULL) { 193 free(pheader); 194 } 195 } 196 } 197 198 // Is it okay to ignore libthread_db failure? Set env var to ignore 199 // libthread_db failure. You can still debug, but will miss threads 200 // related functionality. 201 static bool sa_ignore_threaddb = (getenv("SA_IGNORE_THREADDB") != 0); 202 203 #define HANDLE_THREADDB_FAILURE(msg) \ 204 if (sa_ignore_threaddb) { \ 205 printf("libsaproc WARNING: %s\n", msg); \ 206 return; \ 207 } else { \ 208 THROW_NEW_DEBUGGER_EXCEPTION(msg); \ 209 } 210 211 #define HANDLE_THREADDB_FAILURE_(msg, ret) \ 212 if (sa_ignore_threaddb) { \ 213 printf("libsaproc WARNING: %s\n", msg); \ 214 return ret; \ 215 } else { \ 216 THROW_NEW_DEBUGGER_EXCEPTION_(msg, ret); \ 217 } 218 219 static const char * alt_root = NULL; 220 static int alt_root_len = -1; 221 222 #define SA_ALTROOT "SA_ALTROOT" 223 224 static void init_alt_root() { 225 if (alt_root_len == -1) { 226 alt_root = getenv(SA_ALTROOT); 227 if (alt_root) 228 alt_root_len = strlen(alt_root); 229 else 230 alt_root_len = 0; 231 } 232 } 233 234 // This function is a complete substitute for the open system call 235 // since it's also used to override open calls from libproc to 236 // implement as a pathmap style facility for the SA. If libproc 237 // starts using other interfaces then this might have to extended to 238 // cover other calls. 239 extern "C" int libsaproc_open(const char * name, int oflag, ...) { 240 if (oflag == O_RDONLY) { 241 init_alt_root(); 242 243 if (_libsaproc_debug) { 244 printf("libsaproc DEBUG: libsaproc_open %s\n", name); 245 } 246 247 if (alt_root_len > 0) { 248 int fd = -1; 249 char alt_path[PATH_MAX+1]; 250 251 strcpy(alt_path, alt_root); 252 strcat(alt_path, name); 253 fd = open(alt_path, O_RDONLY); 254 if (fd >= 0) { 255 if (_libsaproc_debug) { 256 printf("libsaproc DEBUG: libsaproc_open substituted %s\n", alt_path); 257 } 258 return fd; 259 } 260 261 if (strrchr(name, '/')) { 262 strcpy(alt_path, alt_root); 263 strcat(alt_path, strrchr(name, '/')); 264 fd = open(alt_path, O_RDONLY); 265 if (fd >= 0) { 266 if (_libsaproc_debug) { 267 printf("libsaproc DEBUG: libsaproc_open substituted %s\n", alt_path); 268 } 269 return fd; 270 } 271 } 272 } 273 } 274 275 { 276 mode_t mode; 277 va_list ap; 278 va_start(ap, oflag); 279 mode = va_arg(ap, mode_t); 280 va_end(ap); 281 282 return open(name, oflag, mode); 283 } 284 } 285 286 287 static void * pathmap_dlopen(const char * name, int mode) { 288 init_alt_root(); 289 290 if (_libsaproc_debug) { 291 printf("libsaproc DEBUG: pathmap_dlopen %s\n", name); 292 } 293 294 void * handle = NULL; 295 if (alt_root_len > 0) { 296 char alt_path[PATH_MAX+1]; 297 strcpy(alt_path, alt_root); 298 strcat(alt_path, name); 299 handle = dlopen(alt_path, mode); 300 if (_libsaproc_debug && handle) { 301 printf("libsaproc DEBUG: pathmap_dlopen substituted %s\n", alt_path); 302 } 303 304 if (handle == NULL && strrchr(name, '/')) { 305 strcpy(alt_path, alt_root); 306 strcat(alt_path, strrchr(name, '/')); 307 handle = dlopen(alt_path, mode); 308 if (_libsaproc_debug && handle) { 309 printf("libsaproc DEBUG: pathmap_dlopen substituted %s\n", alt_path); 310 } 311 } 312 } 313 if (handle == NULL) { 314 handle = dlopen(name, mode); 315 } 316 if (_libsaproc_debug) { 317 printf("libsaproc DEBUG: pathmap_dlopen %s return 0x%lx\n", name, (unsigned long) handle); 318 } 319 return handle; 320 } 321 322 // libproc and libthread_db callback functions 323 324 extern "C" { 325 326 static int 327 init_libthread_db_ptrs(void *cd, const prmap_t *pmp, const char *object_name) { 328 Debugger* dbg = (Debugger*) cd; 329 JNIEnv* env = dbg->env; 330 jobject this_obj = dbg->this_obj; 331 struct ps_prochandle* ph = (struct ps_prochandle*) env->GetLongField(this_obj, p_ps_prochandle_ID); 332 333 char *s1 = 0, *s2 = 0; 334 char libthread_db[PATH_MAX]; 335 336 if (strstr(object_name, "/libthread.so.") == NULL) 337 return (0); 338 339 /* 340 * We found a libthread. 341 * dlopen() the matching libthread_db and get the thread agent handle. 342 */ 343 if (Pstatus(ph)->pr_dmodel == PR_MODEL_NATIVE) { 344 (void) strcpy(libthread_db, object_name); 345 s1 = (char*) strstr(object_name, ".so."); 346 s2 = (char*) strstr(libthread_db, ".so."); 347 (void) strcpy(s2, "_db"); 348 s2 += 3; 349 (void) strcpy(s2, s1); 350 } else { 351 #ifdef _LP64 352 /* 353 * The victim process is 32-bit, we are 64-bit. 354 * We have to find the 64-bit version of libthread_db 355 * that matches the victim's 32-bit version of libthread. 356 */ 357 (void) strcpy(libthread_db, object_name); 358 s1 = (char*) strstr(object_name, "/libthread.so."); 359 s2 = (char*) strstr(libthread_db, "/libthread.so."); 360 (void) strcpy(s2, "/64"); 361 s2 += 3; 362 (void) strcpy(s2, s1); 363 s1 = (char*) strstr(s1, ".so."); 364 s2 = (char*) strstr(s2, ".so."); 365 (void) strcpy(s2, "_db"); 366 s2 += 3; 367 (void) strcpy(s2, s1); 368 #else 369 return (0); 370 #endif /* _LP64 */ 371 } 372 373 void* libthread_db_handle = 0; 374 if ((libthread_db_handle = pathmap_dlopen(libthread_db, RTLD_LAZY|RTLD_LOCAL)) == NULL) { 375 char errMsg[PATH_MAX + 256]; 376 sprintf(errMsg, "Can't load %s!", libthread_db); 377 HANDLE_THREADDB_FAILURE_(errMsg, 0); 378 } 379 env->SetLongField(this_obj, libthread_db_handle_ID, (jlong)(uintptr_t)libthread_db_handle); 380 381 void* tmpPtr = 0; 382 tmpPtr = dlsym(libthread_db_handle, "td_init"); 383 if (tmpPtr == 0) { 384 HANDLE_THREADDB_FAILURE_("dlsym failed on td_init!", 0); 385 } 386 env->SetLongField(this_obj, p_td_init_ID, (jlong)(uintptr_t) tmpPtr); 387 388 tmpPtr =dlsym(libthread_db_handle, "td_ta_new"); 389 if (tmpPtr == 0) { 390 HANDLE_THREADDB_FAILURE_("dlsym failed on td_ta_new!", 0); 391 } 392 env->SetLongField(this_obj, p_td_ta_new_ID, (jlong)(uintptr_t) tmpPtr); 393 394 tmpPtr = dlsym(libthread_db_handle, "td_ta_delete"); 395 if (tmpPtr == 0) { 396 HANDLE_THREADDB_FAILURE_("dlsym failed on td_ta_delete!", 0); 397 } 398 env->SetLongField(this_obj, p_td_ta_delete_ID, (jlong)(uintptr_t) tmpPtr); 399 400 tmpPtr = dlsym(libthread_db_handle, "td_ta_thr_iter"); 401 if (tmpPtr == 0) { 402 HANDLE_THREADDB_FAILURE_("dlsym failed on td_ta_thr_iter!", 0); 403 } 404 env->SetLongField(this_obj, p_td_ta_thr_iter_ID, (jlong)(uintptr_t) tmpPtr); 405 406 tmpPtr = dlsym(libthread_db_handle, "td_thr_get_info"); 407 if (tmpPtr == 0) { 408 HANDLE_THREADDB_FAILURE_("dlsym failed on td_thr_get_info!", 0); 409 } 410 env->SetLongField(this_obj, p_td_thr_get_info_ID, (jlong)(uintptr_t) tmpPtr); 411 412 tmpPtr = dlsym(libthread_db_handle, "td_ta_map_id2thr"); 413 if (tmpPtr == 0) { 414 HANDLE_THREADDB_FAILURE_("dlsym failed on td_ta_map_id2thr!", 0); 415 } 416 env->SetLongField(this_obj, p_td_ta_map_id2thr_ID, (jlong)(uintptr_t) tmpPtr); 417 418 tmpPtr = dlsym(libthread_db_handle, "td_thr_getgregs"); 419 if (tmpPtr == 0) { 420 HANDLE_THREADDB_FAILURE_("dlsym failed on td_thr_getgregs!", 0); 421 } 422 env->SetLongField(this_obj, p_td_thr_getgregs_ID, (jlong)(uintptr_t) tmpPtr); 423 424 return 1; 425 } 426 427 static int 428 fill_thread_list(const td_thrhandle_t *p_td_thragent_t, void* cd) { 429 DebuggerWithObject* dbgo = (DebuggerWithObject*) cd; 430 JNIEnv* env = dbgo->env; 431 jobject this_obj = dbgo->this_obj; 432 jobject list = dbgo->obj; 433 434 td_thrinfo_t thrinfo; 435 p_td_thr_get_info_t p_td_thr_get_info = (p_td_thr_get_info_t) env->GetLongField(this_obj, p_td_thr_get_info_ID); 436 437 if (p_td_thr_get_info(p_td_thragent_t, &thrinfo) != TD_OK) 438 return (0); 439 440 jobject threadProxy = env->CallObjectMethod(this_obj, getThreadForThreadId_ID, (jlong)(uintptr_t) thrinfo.ti_tid); 441 CHECK_EXCEPTION_(1); 442 env->CallBooleanMethod(list, listAdd_ID, threadProxy); 443 CHECK_EXCEPTION_(1); 444 return 0; 445 } 446 447 static int 448 fill_load_object_list(void *cd, const prmap_t* pmp, const char* obj_name) { 449 450 if (obj_name) { 451 DebuggerWithObject* dbgo = (DebuggerWithObject*) cd; 452 JNIEnv* env = dbgo->env; 453 jobject this_obj = dbgo->this_obj; 454 jobject list = dbgo->obj; 455 456 jstring objectName = env->NewStringUTF(obj_name); 457 CHECK_EXCEPTION_(1); 458 459 jlong mapSize = (jlong) pmp->pr_size; 460 jobject sharedObject = env->CallObjectMethod(this_obj, createLoadObject_ID, 461 objectName, mapSize, (jlong)(uintptr_t)pmp->pr_vaddr); 462 CHECK_EXCEPTION_(1); 463 env->CallBooleanMethod(list, listAdd_ID, sharedObject); 464 CHECK_EXCEPTION_(1); 465 } 466 467 return 0; 468 } 469 470 // Pstack_iter() proc_stack_f callback prior to Nevada-B159 471 static int 472 fill_cframe_list(void *cd, const prgregset_t regs, uint_t argc, const long *argv) { 473 DebuggerWith2Objects* dbgo2 = (DebuggerWith2Objects*) cd; 474 JNIEnv* env = dbgo2->env; 475 jobject this_obj = dbgo2->this_obj; 476 jobject curFrame = dbgo2->obj2; 477 478 jint pcRegIndex = env->GetIntField(this_obj, pcRegIndex_ID); 479 jint fpRegIndex = env->GetIntField(this_obj, fpRegIndex_ID); 480 481 jlong pc = (jlong) (uintptr_t) regs[pcRegIndex]; 482 jlong fp = (jlong) (uintptr_t) regs[fpRegIndex]; 483 484 dbgo2->obj2 = env->CallObjectMethod(this_obj, createSenderFrame_ID, 485 curFrame, pc, fp); 486 CHECK_EXCEPTION_(1); 487 if (dbgo2->obj == 0) { 488 dbgo2->obj = dbgo2->obj2; 489 } 490 return 0; 491 } 492 493 // Pstack_iter() proc_stack_f callback in Nevada-B159 or later 494 /*ARGSUSED*/ 495 static int 496 wrapper_fill_cframe_list(void *cd, const prgregset_t regs, uint_t argc, 497 const long *argv, int frame_flags, int sig) { 498 return(fill_cframe_list(cd, regs, argc, argv)); 499 } 500 501 // part of the class sharing workaround 502 503 // FIXME: !!HACK ALERT!! 504 505 // The format of sharing achive file header is needed to read shared heap 506 // file mappings. For now, I am hard coding portion of FileMapHeader here. 507 // Refer to filemap.hpp. 508 509 // FileMapHeader describes the shared space data in the file to be 510 // mapped. This structure gets written to a file. It is not a class, so 511 // that the compilers don't add any compiler-private data to it. 512 513 const int NUM_SHARED_MAPS = 4; 514 515 // Refer to FileMapInfo::_current_version in filemap.hpp 516 const int CURRENT_ARCHIVE_VERSION = 1; 517 518 struct FileMapHeader { 519 int _magic; // identify file type. 520 int _version; // (from enum, above.) 521 size_t _alignment; // how shared archive should be aligned 522 523 524 struct space_info { 525 int _file_offset; // sizeof(this) rounded to vm page size 526 char* _base; // copy-on-write base address 527 size_t _capacity; // for validity checking 528 size_t _used; // for setting space top on read 529 530 bool _read_only; // read only space? 531 bool _allow_exec; // executable code in space? 532 533 } _space[NUM_SHARED_MAPS]; 534 535 // Ignore the rest of the FileMapHeader. We don't need those fields here. 536 }; 537 538 static bool 539 read_jboolean(struct ps_prochandle* ph, psaddr_t addr, jboolean* pvalue) { 540 jboolean i; 541 if (ps_pread(ph, addr, &i, sizeof(i)) == PS_OK) { 542 *pvalue = i; 543 return true; 544 } else { 545 return false; 546 } 547 } 548 549 static bool 550 read_pointer(struct ps_prochandle* ph, psaddr_t addr, uintptr_t* pvalue) { 551 uintptr_t uip; 552 if (ps_pread(ph, addr, &uip, sizeof(uip)) == PS_OK) { 553 *pvalue = uip; 554 return true; 555 } else { 556 return false; 557 } 558 } 559 560 static bool 561 read_string(struct ps_prochandle* ph, psaddr_t addr, char* buf, size_t size) { 562 char ch = ' '; 563 size_t i = 0; 564 565 while (ch != '\0') { 566 if (ps_pread(ph, addr, &ch, sizeof(ch)) != PS_OK) 567 return false; 568 569 if (i < size - 1) { 570 buf[i] = ch; 571 } else { // smaller buffer 572 return false; 573 } 574 575 i++; addr++; 576 } 577 578 buf[i] = '\0'; 579 return true; 580 } 581 582 #define USE_SHARED_SPACES_SYM "UseSharedSpaces" 583 // mangled symbol name for Arguments::SharedArchivePath 584 #define SHARED_ARCHIVE_PATH_SYM "__1cJArgumentsRSharedArchivePath_" 585 586 static int 587 init_classsharing_workaround(void *cd, const prmap_t* pmap, const char* obj_name) { 588 Debugger* dbg = (Debugger*) cd; 589 JNIEnv* env = dbg->env; 590 jobject this_obj = dbg->this_obj; 591 const char* jvm_name = 0; 592 if ((jvm_name = strstr(obj_name, "libjvm.so")) != NULL) { 593 jvm_name = obj_name; 594 } else { 595 return 0; 596 } 597 598 struct ps_prochandle* ph = (struct ps_prochandle*) env->GetLongField(this_obj, p_ps_prochandle_ID); 599 600 // initialize classes.jsa file descriptor field. 601 dbg->env->SetIntField(this_obj, classes_jsa_fd_ID, -1); 602 603 // check whether class sharing is on by reading variable "UseSharedSpaces" 604 psaddr_t useSharedSpacesAddr = 0; 605 ps_pglobal_lookup(ph, jvm_name, USE_SHARED_SPACES_SYM, &useSharedSpacesAddr); 606 if (useSharedSpacesAddr == 0) { 607 THROW_NEW_DEBUGGER_EXCEPTION_("can't find 'UseSharedSpaces' flag\n", 1); 608 } 609 610 // read the value of the flag "UseSharedSpaces" 611 // Since hotspot types are not available to build this library. So 612 // equivalent type "jboolean" is used to read the value of "UseSharedSpaces" 613 // which is same as hotspot type "bool". 614 jboolean value = 0; 615 if (read_jboolean(ph, useSharedSpacesAddr, &value) != true) { 616 THROW_NEW_DEBUGGER_EXCEPTION_("can't read 'UseSharedSpaces' flag", 1); 617 } else if ((int)value == 0) { 618 print_debug("UseSharedSpaces is false, assuming -Xshare:off!\n"); 619 return 1; 620 } 621 622 char classes_jsa[PATH_MAX]; 623 psaddr_t sharedArchivePathAddrAddr = 0; 624 ps_pglobal_lookup(ph, jvm_name, SHARED_ARCHIVE_PATH_SYM, &sharedArchivePathAddrAddr); 625 if (sharedArchivePathAddrAddr == 0) { 626 print_debug("can't find symbol 'Arguments::SharedArchivePath'\n"); 627 THROW_NEW_DEBUGGER_EXCEPTION_("can't get shared archive path from debuggee", 1); 628 } 629 630 uintptr_t sharedArchivePathAddr = 0; 631 if (read_pointer(ph, sharedArchivePathAddrAddr, &sharedArchivePathAddr) != true) { 632 print_debug("can't find read pointer 'Arguments::SharedArchivePath'\n"); 633 THROW_NEW_DEBUGGER_EXCEPTION_("can't get shared archive path from debuggee", 1); 634 } 635 636 if (read_string(ph, (psaddr_t)sharedArchivePathAddr, classes_jsa, sizeof(classes_jsa)) != true) { 637 print_debug("can't find read 'Arguments::SharedArchivePath' value\n"); 638 THROW_NEW_DEBUGGER_EXCEPTION_("can't get shared archive path from debuggee", 1); 639 } 640 641 print_debug("looking for %s\n", classes_jsa); 642 643 // open the classes.jsa 644 int fd = libsaproc_open(classes_jsa, O_RDONLY); 645 if (fd < 0) { 646 char errMsg[ERR_MSG_SIZE]; 647 sprintf(errMsg, "can't open shared archive file %s", classes_jsa); 648 THROW_NEW_DEBUGGER_EXCEPTION_(errMsg, 1); 649 } else { 650 print_debug("opened shared archive file %s\n", classes_jsa); 651 } 652 653 // parse classes.jsa 654 struct FileMapHeader* pheader = (struct FileMapHeader*) malloc(sizeof(struct FileMapHeader)); 655 if (pheader == NULL) { 656 close(fd); 657 THROW_NEW_DEBUGGER_EXCEPTION_("can't allocate memory for shared file map header", 1); 658 } 659 660 memset(pheader, 0, sizeof(struct FileMapHeader)); 661 // read FileMapHeader 662 size_t n = read(fd, pheader, sizeof(struct FileMapHeader)); 663 if (n != sizeof(struct FileMapHeader)) { 664 char errMsg[ERR_MSG_SIZE]; 665 sprintf(errMsg, "unable to read shared archive file map header from %s", classes_jsa); 666 close(fd); 667 free(pheader); 668 THROW_NEW_DEBUGGER_EXCEPTION_(errMsg, 1); 669 } 670 671 // check file magic 672 if (pheader->_magic != 0xf00baba2) { 673 char errMsg[ERR_MSG_SIZE]; 674 sprintf(errMsg, "%s has bad shared archive magic 0x%x, expecting 0xf00baba2", 675 classes_jsa, pheader->_magic); 676 close(fd); 677 free(pheader); 678 THROW_NEW_DEBUGGER_EXCEPTION_(errMsg, 1); 679 } 680 681 // check version 682 if (pheader->_version != CURRENT_ARCHIVE_VERSION) { 683 char errMsg[ERR_MSG_SIZE]; 684 sprintf(errMsg, "%s has wrong shared archive version %d, expecting %d", 685 classes_jsa, pheader->_version, CURRENT_ARCHIVE_VERSION); 686 close(fd); 687 free(pheader); 688 THROW_NEW_DEBUGGER_EXCEPTION_(errMsg, 1); 689 } 690 691 if (_libsaproc_debug) { 692 for (int m = 0; m < NUM_SHARED_MAPS; m++) { 693 print_debug("shared file offset %d mapped at 0x%lx, size = %ld, read only? = %d\n", 694 pheader->_space[m]._file_offset, pheader->_space[m]._base, 695 pheader->_space[m]._used, pheader->_space[m]._read_only); 696 } 697 } 698 699 // FIXME: For now, omitting other checks such as VM version etc. 700 701 // store class archive file fd and map header in debugger object fields 702 dbg->env->SetIntField(this_obj, classes_jsa_fd_ID, fd); 703 dbg->env->SetLongField(this_obj, p_file_map_header_ID, (jlong)(uintptr_t) pheader); 704 return 1; 705 } 706 707 } // extern "C" 708 709 // error messages for proc_arg_grab failure codes. The messages are 710 // modified versions of comments against corresponding #defines in 711 // libproc.h. 712 static const char* proc_arg_grab_errmsgs[] = { 713 "", 714 /* G_NOPROC */ "No such process", 715 /* G_NOCORE */ "No such core file", 716 /* G_NOPROCORCORE */ "No such process or core", 717 /* G_NOEXEC */ "Cannot locate executable file", 718 /* G_ZOMB */ "Zombie processs", 719 /* G_PERM */ "No permission to attach", 720 /* G_BUSY */ "Another process has already attached", 721 /* G_SYS */ "System process - can not attach", 722 /* G_SELF */ "Process is self - can't debug myself!", 723 /* G_INTR */ "Interrupt received while grabbing", 724 /* G_LP64 */ "debuggee is 64 bit, use java -d64 for debugger", 725 /* G_FORMAT */ "File is not an ELF format core file - corrupted core?", 726 /* G_ELF */ "Libelf error while parsing an ELF file", 727 /* G_NOTE */ "Required PT_NOTE Phdr not present - corrupted core?", 728 }; 729 730 static void attach_internal(JNIEnv* env, jobject this_obj, jstring cmdLine, jboolean isProcess) { 731 jboolean isCopy; 732 int gcode; 733 const char* cmdLine_cstr = env->GetStringUTFChars(cmdLine, &isCopy); 734 CHECK_EXCEPTION; 735 736 // some older versions of libproc.so crash when trying to attach 32 bit 737 // debugger to 64 bit core file. check and throw error. 738 #ifndef _LP64 739 atoi(cmdLine_cstr); 740 if (errno) { 741 // core file 742 int core_fd; 743 if ((core_fd = open64(cmdLine_cstr, O_RDONLY)) >= 0) { 744 Elf32_Ehdr e32; 745 if (pread64(core_fd, &e32, sizeof (e32), 0) == sizeof (e32) && 746 memcmp(&e32.e_ident[EI_MAG0], ELFMAG, SELFMAG) == 0 && 747 e32.e_type == ET_CORE && e32.e_ident[EI_CLASS] == ELFCLASS64) { 748 close(core_fd); 749 THROW_NEW_DEBUGGER_EXCEPTION("debuggee is 64 bit, use java -d64 for debugger"); 750 } 751 close(core_fd); 752 } 753 // all other conditions are handled by libproc.so. 754 } 755 #endif 756 757 // connect to process/core 758 ps_prochandle_t* ph = proc_arg_grab(cmdLine_cstr, (isProcess? PR_ARG_PIDS : PR_ARG_CORES), PGRAB_FORCE, &gcode, NULL); 759 760 env->ReleaseStringUTFChars(cmdLine, cmdLine_cstr); 761 if (! ph) { 762 if (gcode > 0 && gcode < sizeof(proc_arg_grab_errmsgs)/sizeof(const char*)) { 763 char errMsg[ERR_MSG_SIZE]; 764 sprintf(errMsg, "Attach failed : %s", proc_arg_grab_errmsgs[gcode]); 765 THROW_NEW_DEBUGGER_EXCEPTION(errMsg); 766 } else { 767 if (_libsaproc_debug && gcode == G_STRANGE) { 768 perror("libsaproc DEBUG: "); 769 } 770 if (isProcess) { 771 THROW_NEW_DEBUGGER_EXCEPTION("Not able to attach to process!"); 772 } else { 773 THROW_NEW_DEBUGGER_EXCEPTION("Not able to attach to core file!"); 774 } 775 } 776 } 777 778 // even though libproc.so supports 64 bit debugger and 32 bit debuggee, we don't 779 // support such cross-bit-debugging. check for that combination and throw error. 780 #ifdef _LP64 781 int data_model; 782 if (ps_pdmodel(ph, &data_model) != PS_OK) { 783 Prelease(ph, PRELEASE_CLEAR); 784 THROW_NEW_DEBUGGER_EXCEPTION("can't determine debuggee data model (ILP32? or LP64?)"); 785 } 786 if (data_model == PR_MODEL_ILP32) { 787 Prelease(ph, PRELEASE_CLEAR); 788 THROW_NEW_DEBUGGER_EXCEPTION("debuggee is 32 bit, use 32 bit java for debugger"); 789 } 790 #endif 791 792 env->SetLongField(this_obj, p_ps_prochandle_ID, (jlong)(uintptr_t)ph); 793 794 Debugger dbg; 795 dbg.env = env; 796 dbg.this_obj = this_obj; 797 jthrowable exception = 0; 798 if (! isProcess) { 799 /* 800 * With class sharing, shared perm. gen heap is allocated in with MAP_SHARED|PROT_READ. 801 * These pages are mapped from the file "classes.jsa". MAP_SHARED pages are not dumped 802 * in Solaris core.To read shared heap pages, we have to read classes.jsa file. 803 */ 804 Pobject_iter(ph, init_classsharing_workaround, &dbg); 805 exception = env->ExceptionOccurred(); 806 if (exception) { 807 env->ExceptionClear(); 808 detach_internal(env, this_obj); 809 env->Throw(exception); 810 return; 811 } 812 } 813 814 /* 815 * Iterate over the process mappings looking 816 * for libthread and then dlopen the appropriate 817 * libthread_db and get function pointers. 818 */ 819 Pobject_iter(ph, init_libthread_db_ptrs, &dbg); 820 exception = env->ExceptionOccurred(); 821 if (exception) { 822 env->ExceptionClear(); 823 if (!sa_ignore_threaddb) { 824 detach_internal(env, this_obj); 825 env->Throw(exception); 826 } 827 return; 828 } 829 830 // init libthread_db and create thread_db agent 831 p_td_init_t p_td_init = (p_td_init_t) env->GetLongField(this_obj, p_td_init_ID); 832 if (p_td_init == 0) { 833 if (!sa_ignore_threaddb) { 834 detach_internal(env, this_obj); 835 } 836 HANDLE_THREADDB_FAILURE("Did not find libthread in target process/core!"); 837 } 838 839 if (p_td_init() != TD_OK) { 840 if (!sa_ignore_threaddb) { 841 detach_internal(env, this_obj); 842 } 843 HANDLE_THREADDB_FAILURE("Can't initialize thread_db!"); 844 } 845 846 p_td_ta_new_t p_td_ta_new = (p_td_ta_new_t) env->GetLongField(this_obj, p_td_ta_new_ID); 847 848 td_thragent_t *p_td_thragent_t = 0; 849 if (p_td_ta_new(ph, &p_td_thragent_t) != TD_OK) { 850 if (!sa_ignore_threaddb) { 851 detach_internal(env, this_obj); 852 } 853 HANDLE_THREADDB_FAILURE("Can't create thread_db agent!"); 854 } 855 env->SetLongField(this_obj, p_td_thragent_t_ID, (jlong)(uintptr_t) p_td_thragent_t); 856 857 } 858 859 /* 860 * Class: sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal 861 * Method: attach0 862 * Signature: (Ljava/lang/String;)V 863 * Description: process detach 864 */ 865 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal_attach0__Ljava_lang_String_2 866 (JNIEnv *env, jobject this_obj, jstring pid) { 867 attach_internal(env, this_obj, pid, JNI_TRUE); 868 } 869 870 /* 871 * Class: sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal 872 * Method: attach0 873 * Signature: (Ljava/lang/String;Ljava/lang/String;)V 874 * Description: core file detach 875 */ 876 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal_attach0__Ljava_lang_String_2Ljava_lang_String_2 877 (JNIEnv *env, jobject this_obj, jstring executable, jstring corefile) { 878 // ignore executable file name, libproc.so can detect a.out name anyway. 879 attach_internal(env, this_obj, corefile, JNI_FALSE); 880 } 881 882 883 /* 884 * Class: sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal 885 * Method: detach0 886 * Signature: ()V 887 * Description: process/core file detach 888 */ 889 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal_detach0 890 (JNIEnv *env, jobject this_obj) { 891 detach_internal(env, this_obj); 892 } 893 894 /* 895 * Class: sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal 896 * Method: getRemoteProcessAddressSize0 897 * Signature: ()I 898 * Description: get process/core address size 899 */ 900 JNIEXPORT jint JNICALL Java_sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal_getRemoteProcessAddressSize0 901 (JNIEnv *env, jobject this_obj) { 902 jlong p_ps_prochandle; 903 p_ps_prochandle = env->GetLongField(this_obj, p_ps_prochandle_ID); 904 int data_model = PR_MODEL_ILP32; 905 ps_pdmodel((struct ps_prochandle*) p_ps_prochandle, &data_model); 906 print_debug("debuggee is %d bit\n", data_model == PR_MODEL_ILP32? 32 : 64); 907 return (jint) data_model == PR_MODEL_ILP32? 32 : 64; 908 } 909 910 /* 911 * Class: sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal 912 * Method: getPageSize0 913 * Signature: ()I 914 * Description: get process/core page size 915 */ 916 JNIEXPORT jint JNICALL Java_sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal_getPageSize0 917 (JNIEnv *env, jobject this_obj) { 918 919 /* 920 We are not yet attached to a java process or core file. getPageSize is called from 921 the constructor of ProcDebuggerLocal. The following won't work! 922 923 jlong p_ps_prochandle; 924 p_ps_prochandle = env->GetLongField(this_obj, p_ps_prochandle_ID); 925 CHECK_EXCEPTION_(-1); 926 struct ps_prochandle* prochandle = (struct ps_prochandle*) p_ps_prochandle; 927 return (Pstate(prochandle) == PS_DEAD) ? Pgetauxval(prochandle, AT_PAGESZ) 928 : getpagesize(); 929 930 So even though core may have been generated with a different page size settings, for now 931 call getpagesize. 932 */ 933 934 return getpagesize(); 935 } 936 937 /* 938 * Class: sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal 939 * Method: getThreadIntegerRegisterSet0 940 * Signature: (J)[J 941 * Description: get gregset for a given thread specified by thread id 942 */ 943 JNIEXPORT jlongArray JNICALL Java_sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal_getThreadIntegerRegisterSet0 944 (JNIEnv *env, jobject this_obj, jlong tid) { 945 // map the thread id to thread handle 946 p_td_ta_map_id2thr_t p_td_ta_map_id2thr = (p_td_ta_map_id2thr_t) env->GetLongField(this_obj, p_td_ta_map_id2thr_ID); 947 948 td_thragent_t* p_td_thragent_t = (td_thragent_t*) env->GetLongField(this_obj, p_td_thragent_t_ID); 949 if (p_td_thragent_t == 0) { 950 return 0; 951 } 952 953 td_thrhandle_t thr_handle; 954 if (p_td_ta_map_id2thr(p_td_thragent_t, (thread_t) tid, &thr_handle) != TD_OK) { 955 THROW_NEW_DEBUGGER_EXCEPTION_("can't map thread id to thread handle!", 0); 956 } 957 958 p_td_thr_getgregs_t p_td_thr_getgregs = (p_td_thr_getgregs_t) env->GetLongField(this_obj, p_td_thr_getgregs_ID); 959 prgregset_t gregs; 960 p_td_thr_getgregs(&thr_handle, gregs); 961 962 jlongArray res = env->NewLongArray(NPRGREG); 963 CHECK_EXCEPTION_(0); 964 jboolean isCopy; 965 jlong* ptr = env->GetLongArrayElements(res, &isCopy); 966 for (int i = 0; i < NPRGREG; i++) { 967 ptr[i] = (jlong) (uintptr_t) gregs[i]; 968 } 969 env->ReleaseLongArrayElements(res, ptr, JNI_COMMIT); 970 return res; 971 } 972 973 /* 974 * Class: sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal 975 * Method: fillThreadList0 976 * Signature: (Ljava/util/List;)V 977 * Description: fills thread list of the debuggee process/core 978 */ 979 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal_fillThreadList0 980 (JNIEnv *env, jobject this_obj, jobject list) { 981 982 td_thragent_t* p_td_thragent_t = (td_thragent_t*) env->GetLongField(this_obj, p_td_thragent_t_ID); 983 if (p_td_thragent_t == 0) { 984 return; 985 } 986 987 p_td_ta_thr_iter_t p_td_ta_thr_iter = (p_td_ta_thr_iter_t) env->GetLongField(this_obj, p_td_ta_thr_iter_ID); 988 989 DebuggerWithObject dbgo; 990 dbgo.env = env; 991 dbgo.this_obj = this_obj; 992 dbgo.obj = list; 993 994 p_td_ta_thr_iter(p_td_thragent_t, fill_thread_list, &dbgo, 995 TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY, TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS); 996 } 997 998 #ifndef SOLARIS_11_B159_OR_LATER 999 // building on Nevada-B158 or earlier so more hoops to jump through 1000 static bool has_newer_Pstack_iter = false; // older version by default 1001 #endif 1002 1003 /* 1004 * Class: sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal 1005 * Method: fillCFrameList0 1006 * Signature: ([J)Lsun/jvm/hotspot/debugger/proc/ProcCFrame; 1007 * Description: fills CFrame list for a given thread 1008 */ 1009 JNIEXPORT jobject JNICALL Java_sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal_fillCFrameList0 1010 (JNIEnv *env, jobject this_obj, jlongArray regsArray) { 1011 jlong p_ps_prochandle = env->GetLongField(this_obj, p_ps_prochandle_ID); 1012 1013 DebuggerWith2Objects dbgo2; 1014 dbgo2.env = env; 1015 dbgo2.this_obj = this_obj; 1016 dbgo2.obj = NULL; 1017 dbgo2.obj2 = NULL; 1018 1019 jboolean isCopy; 1020 jlong* ptr = env->GetLongArrayElements(regsArray, &isCopy); 1021 CHECK_EXCEPTION_(0); 1022 1023 prgregset_t gregs; 1024 for (int i = 0; i < NPRGREG; i++) { 1025 gregs[i] = (uintptr_t) ptr[i]; 1026 } 1027 1028 env->ReleaseLongArrayElements(regsArray, ptr, JNI_ABORT); 1029 CHECK_EXCEPTION_(0); 1030 1031 #ifdef SOLARIS_11_B159_OR_LATER 1032 // building on Nevada-B159 or later so use the new callback 1033 Pstack_iter((struct ps_prochandle*) p_ps_prochandle, gregs, 1034 wrapper_fill_cframe_list, &dbgo2); 1035 #else 1036 // building on Nevada-B158 or earlier so figure out which callback to use 1037 1038 if (has_newer_Pstack_iter) { 1039 // Since we're building on Nevada-B158 or earlier, we have to 1040 // cast wrapper_fill_cframe_list to make the compiler happy. 1041 Pstack_iter((struct ps_prochandle*) p_ps_prochandle, gregs, 1042 (proc_stack_f *)wrapper_fill_cframe_list, &dbgo2); 1043 } else { 1044 Pstack_iter((struct ps_prochandle*) p_ps_prochandle, gregs, 1045 fill_cframe_list, &dbgo2); 1046 } 1047 #endif // SOLARIS_11_B159_OR_LATER 1048 return dbgo2.obj; 1049 } 1050 1051 /* 1052 * Class: sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal 1053 * Method: fillLoadObjectList0 1054 * Signature: (Ljava/util/List;)V 1055 * Description: fills shared objects of the debuggee process/core 1056 */ 1057 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal_fillLoadObjectList0 1058 (JNIEnv *env, jobject this_obj, jobject list) { 1059 DebuggerWithObject dbgo; 1060 dbgo.env = env; 1061 dbgo.this_obj = this_obj; 1062 dbgo.obj = list; 1063 1064 jlong p_ps_prochandle = env->GetLongField(this_obj, p_ps_prochandle_ID); 1065 Pobject_iter((struct ps_prochandle*) p_ps_prochandle, fill_load_object_list, &dbgo); 1066 } 1067 1068 /* 1069 * Class: sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal 1070 * Method: readBytesFromProcess0 1071 * Signature: (JJ)[B 1072 * Description: read bytes from debuggee process/core 1073 */ 1074 JNIEXPORT jbyteArray JNICALL Java_sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal_readBytesFromProcess0 1075 (JNIEnv *env, jobject this_obj, jlong address, jlong numBytes) { 1076 1077 jbyteArray array = env->NewByteArray(numBytes); 1078 CHECK_EXCEPTION_(0); 1079 jboolean isCopy; 1080 jbyte* bufPtr = env->GetByteArrayElements(array, &isCopy); 1081 CHECK_EXCEPTION_(0); 1082 1083 jlong p_ps_prochandle = env->GetLongField(this_obj, p_ps_prochandle_ID); 1084 ps_err_e ret = ps_pread((struct ps_prochandle*) p_ps_prochandle, 1085 (psaddr_t)address, bufPtr, (size_t)numBytes); 1086 1087 if (ret != PS_OK) { 1088 // part of the class sharing workaround. try shared heap area 1089 int classes_jsa_fd = env->GetIntField(this_obj, classes_jsa_fd_ID); 1090 if (classes_jsa_fd != -1 && address != (jlong)0) { 1091 print_debug("read failed at 0x%lx, attempting shared heap area\n", (long) address); 1092 1093 struct FileMapHeader* pheader = (struct FileMapHeader*) env->GetLongField(this_obj, p_file_map_header_ID); 1094 // walk through the shared mappings -- we just have 4 of them. 1095 // so, linear walking is okay. 1096 for (int m = 0; m < NUM_SHARED_MAPS; m++) { 1097 1098 // We can skip the non-read-only maps. These are mapped as MAP_PRIVATE 1099 // and hence will be read by libproc. Besides, the file copy may be 1100 // stale because the process might have modified those pages. 1101 if (pheader->_space[m]._read_only) { 1102 jlong baseAddress = (jlong) (uintptr_t) pheader->_space[m]._base; 1103 size_t usedSize = pheader->_space[m]._used; 1104 if (address >= baseAddress && address < (baseAddress + usedSize)) { 1105 // the given address falls in this shared heap area 1106 print_debug("found shared map at 0x%lx\n", (long) baseAddress); 1107 1108 1109 // If more data is asked than actually mapped from file, we need to zero fill 1110 // till the end-of-page boundary. But, java array new does that for us. we just 1111 // need to read as much as data available. 1112 1113 #define MIN2(x, y) (((x) < (y))? (x) : (y)) 1114 1115 jlong diff = address - baseAddress; 1116 jlong bytesToRead = MIN2(numBytes, usedSize - diff); 1117 off_t offset = pheader->_space[m]._file_offset + off_t(diff); 1118 ssize_t bytesRead = pread(classes_jsa_fd, bufPtr, bytesToRead, offset); 1119 if (bytesRead != bytesToRead) { 1120 env->ReleaseByteArrayElements(array, bufPtr, JNI_ABORT); 1121 print_debug("shared map read failed\n"); 1122 return jbyteArray(0); 1123 } else { 1124 print_debug("shared map read succeeded\n"); 1125 env->ReleaseByteArrayElements(array, bufPtr, 0); 1126 return array; 1127 } 1128 } // is in current map 1129 } // is read only map 1130 } // for shared maps 1131 } // classes_jsa_fd != -1 1132 env->ReleaseByteArrayElements(array, bufPtr, JNI_ABORT); 1133 return jbyteArray(0); 1134 } else { 1135 env->ReleaseByteArrayElements(array, bufPtr, 0); 1136 return array; 1137 } 1138 } 1139 1140 /* 1141 * Class: sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal 1142 * Method: writeBytesToProcess0 1143 * Signature: (JJ[B)V 1144 * Description: write bytes into debugger process 1145 */ 1146 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal_writeBytesToProcess0 1147 (JNIEnv *env, jobject this_obj, jlong address, jlong numBytes, jbyteArray data) { 1148 jlong p_ps_prochandle = env->GetLongField(this_obj, p_ps_prochandle_ID); 1149 jboolean isCopy; 1150 jbyte* ptr = env->GetByteArrayElements(data, &isCopy); 1151 CHECK_EXCEPTION; 1152 1153 if (ps_pwrite((struct ps_prochandle*) p_ps_prochandle, address, ptr, numBytes) != PS_OK) { 1154 env->ReleaseByteArrayElements(data, ptr, JNI_ABORT); 1155 THROW_NEW_DEBUGGER_EXCEPTION("Process write failed!"); 1156 } 1157 1158 env->ReleaseByteArrayElements(data, ptr, JNI_ABORT); 1159 } 1160 1161 /* 1162 * Class: sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal 1163 * Method: suspend0 1164 * Signature: ()V 1165 */ 1166 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal_suspend0 1167 (JNIEnv *env, jobject this_obj) { 1168 jlong p_ps_prochandle = env->GetLongField(this_obj, p_ps_prochandle_ID); 1169 // for now don't check return value. revisit this again. 1170 Pstop((struct ps_prochandle*) p_ps_prochandle, 1000); 1171 } 1172 1173 /* 1174 * Class: sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal 1175 * Method: resume0 1176 * Signature: ()V 1177 */ 1178 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal_resume0 1179 (JNIEnv *env, jobject this_obj) { 1180 jlong p_ps_prochandle = env->GetLongField(this_obj, p_ps_prochandle_ID); 1181 // for now don't check return value. revisit this again. 1182 Psetrun((struct ps_prochandle*) p_ps_prochandle, 0, PRCFAULT|PRSTOP); 1183 } 1184 1185 /* 1186 * Class: sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal 1187 * Method: lookupByName0 1188 * Signature: (Ljava/lang/String;Ljava/lang/String;)J 1189 * Description: symbol lookup by name 1190 */ 1191 JNIEXPORT jlong JNICALL Java_sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal_lookupByName0 1192 (JNIEnv *env, jobject this_obj, jstring objectName, jstring symbolName) { 1193 jlong p_ps_prochandle; 1194 p_ps_prochandle = env->GetLongField(this_obj, p_ps_prochandle_ID); 1195 1196 jboolean isCopy; 1197 const char* objectName_cstr = NULL; 1198 if (objectName != NULL) { 1199 objectName_cstr = env->GetStringUTFChars(objectName, &isCopy); 1200 CHECK_EXCEPTION_(0); 1201 } else { 1202 objectName_cstr = PR_OBJ_EVERY; 1203 } 1204 1205 const char* symbolName_cstr = env->GetStringUTFChars(symbolName, &isCopy); 1206 CHECK_EXCEPTION_(0); 1207 1208 psaddr_t symbol_addr = (psaddr_t) 0; 1209 ps_pglobal_lookup((struct ps_prochandle*) p_ps_prochandle, objectName_cstr, 1210 symbolName_cstr, &symbol_addr); 1211 1212 if (symbol_addr == 0) { 1213 print_debug("lookup for %s in %s failed\n", symbolName_cstr, objectName_cstr); 1214 } 1215 1216 if (objectName_cstr != PR_OBJ_EVERY) { 1217 env->ReleaseStringUTFChars(objectName, objectName_cstr); 1218 } 1219 env->ReleaseStringUTFChars(symbolName, symbolName_cstr); 1220 return (jlong) (uintptr_t) symbol_addr; 1221 } 1222 1223 /* 1224 * Class: sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal 1225 * Method: lookupByAddress0 1226 * Signature: (J)Lsun/jvm/hotspot/debugger/cdbg/ClosestSymbol; 1227 * Description: lookup symbol name for a given address 1228 */ 1229 JNIEXPORT jobject JNICALL Java_sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal_lookupByAddress0 1230 (JNIEnv *env, jobject this_obj, jlong address) { 1231 jlong p_ps_prochandle; 1232 p_ps_prochandle = env->GetLongField(this_obj, p_ps_prochandle_ID); 1233 1234 char nameBuf[SYMBOL_BUF_SIZE + 1]; 1235 GElf_Sym sym; 1236 int res = Plookup_by_addr((struct ps_prochandle*) p_ps_prochandle, (uintptr_t) address, 1237 nameBuf, sizeof(nameBuf), &sym, NULL); 1238 1239 if (res != 0) { // failed 1240 return 0; 1241 } 1242 1243 jstring resSym = env->NewStringUTF(nameBuf); 1244 CHECK_EXCEPTION_(0); 1245 1246 return env->CallObjectMethod(this_obj, createClosestSymbol_ID, resSym, (address - sym.st_value)); 1247 } 1248 1249 /* 1250 * Class: sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal 1251 * Method: demangle0 1252 * Signature: (Ljava/lang/String;)Ljava/lang/String; 1253 */ 1254 JNIEXPORT jstring JNICALL Java_sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal_demangle0 1255 (JNIEnv *env, jobject this_object, jstring name) { 1256 jboolean isCopy; 1257 const char* ptr = env->GetStringUTFChars(name, &isCopy); 1258 char buf[2*SYMBOL_BUF_SIZE + 1]; 1259 jstring res = 0; 1260 if (cplus_demangle((char*) ptr, buf, sizeof(buf)) != DEMANGLE_ESPACE) { 1261 res = env->NewStringUTF(buf); 1262 } else { 1263 res = name; 1264 } 1265 env->ReleaseStringUTFChars(name, ptr); 1266 return res; 1267 } 1268 1269 #ifndef SOLARIS_11_B159_OR_LATER 1270 // Determine if the OS we're running on has the newer version 1271 // of libproc's Pstack_iter. 1272 // 1273 // Set env var PSTACK_ITER_DEBUG=true to debug this logic. 1274 // Set env var PSTACK_ITER_DEBUG_RELEASE to simulate a 'release' value. 1275 // Set env var PSTACK_ITER_DEBUG_VERSION to simulate a 'version' value. 1276 // 1277 // frankenputer 'uname -r -v': 5.10 Generic_141445-09 1278 // jurassic 'uname -r -v': 5.11 snv_164 1279 // lonepeak 'uname -r -v': 5.11 snv_127 1280 // 1281 static void set_has_newer_Pstack_iter(JNIEnv *env) { 1282 static bool done_set = false; 1283 1284 if (done_set) { 1285 // already set has_newer_Pstack_iter 1286 return; 1287 } 1288 1289 struct utsname name; 1290 if (uname(&name) == -1) { 1291 THROW_NEW_DEBUGGER_EXCEPTION("uname() failed!"); 1292 } 1293 dprintf_2("release='%s' version='%s'\n", name.release, name.version); 1294 1295 if (_Pstack_iter_debug) { 1296 char *override = getenv("PSTACK_ITER_DEBUG_RELEASE"); 1297 if (override != NULL) { 1298 strncpy(name.release, override, SYS_NMLN - 1); 1299 name.release[SYS_NMLN - 2] = '\0'; 1300 dprintf_2("overriding with release='%s'\n", name.release); 1301 } 1302 override = getenv("PSTACK_ITER_DEBUG_VERSION"); 1303 if (override != NULL) { 1304 strncpy(name.version, override, SYS_NMLN - 1); 1305 name.version[SYS_NMLN - 2] = '\0'; 1306 dprintf_2("overriding with version='%s'\n", name.version); 1307 } 1308 } 1309 1310 // the major number corresponds to the old SunOS major number 1311 int major = atoi(name.release); 1312 if (major >= 6) { 1313 dprintf_2("release is SunOS 6 or later\n"); 1314 has_newer_Pstack_iter = true; 1315 done_set = true; 1316 return; 1317 } 1318 if (major < 5) { 1319 dprintf_2("release is SunOS 4 or earlier\n"); 1320 done_set = true; 1321 return; 1322 } 1323 1324 // some SunOS 5.* build so now check for Solaris versions 1325 char *dot = strchr(name.release, '.'); 1326 int minor = 0; 1327 if (dot != NULL) { 1328 // release is major.minor format 1329 *dot = NULL; 1330 minor = atoi(dot + 1); 1331 } 1332 1333 if (minor <= 10) { 1334 dprintf_2("release is Solaris 10 or earlier\n"); 1335 done_set = true; 1336 return; 1337 } else if (minor >= 12) { 1338 dprintf_2("release is Solaris 12 or later\n"); 1339 has_newer_Pstack_iter = true; 1340 done_set = true; 1341 return; 1342 } 1343 1344 // some Solaris 11 build so now check for internal build numbers 1345 if (strncmp(name.version, "snv_", 4) != 0) { 1346 dprintf_2("release is Solaris 11 post-GA or later\n"); 1347 has_newer_Pstack_iter = true; 1348 done_set = true; 1349 return; 1350 } 1351 1352 // version begins with "snv_" so a pre-GA build of Solaris 11 1353 int build = atoi(&name.version[4]); 1354 if (build >= 159) { 1355 dprintf_2("release is Nevada-B159 or later\n"); 1356 has_newer_Pstack_iter = true; 1357 } else { 1358 dprintf_2("release is Nevada-B158 or earlier\n"); 1359 } 1360 1361 done_set = true; 1362 } 1363 #endif // !SOLARIS_11_B159_OR_LATER 1364 1365 /* 1366 * Class: sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal 1367 * Method: initIDs 1368 * Signature: ()V 1369 * Description: get JNI ids for fields and methods of ProcDebuggerLocal class 1370 */ 1371 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal_initIDs 1372 (JNIEnv *env, jclass clazz) { 1373 _libsaproc_debug = getenv("LIBSAPROC_DEBUG") != NULL; 1374 if (_libsaproc_debug) { 1375 // propagate debug mode to libproc.so 1376 static const char* var = "LIBPROC_DEBUG=1"; 1377 putenv((char*)var); 1378 } 1379 1380 void* libproc_handle = dlopen("libproc.so", RTLD_LAZY | RTLD_GLOBAL); 1381 if (libproc_handle == 0) 1382 THROW_NEW_DEBUGGER_EXCEPTION("can't load libproc.so, if you are using Solaris 5.7 or below, copy libproc.so from 5.8!"); 1383 1384 #ifndef SOLARIS_11_B159_OR_LATER 1385 _Pstack_iter_debug = getenv("PSTACK_ITER_DEBUG") != NULL; 1386 1387 set_has_newer_Pstack_iter(env); 1388 CHECK_EXCEPTION; 1389 dprintf_2("has_newer_Pstack_iter=%d\n", has_newer_Pstack_iter); 1390 #endif 1391 1392 p_ps_prochandle_ID = env->GetFieldID(clazz, "p_ps_prochandle", "J"); 1393 CHECK_EXCEPTION; 1394 1395 libthread_db_handle_ID = env->GetFieldID(clazz, "libthread_db_handle", "J"); 1396 CHECK_EXCEPTION; 1397 1398 p_td_thragent_t_ID = env->GetFieldID(clazz, "p_td_thragent_t", "J"); 1399 CHECK_EXCEPTION; 1400 1401 p_td_init_ID = env->GetFieldID(clazz, "p_td_init", "J"); 1402 CHECK_EXCEPTION; 1403 1404 p_td_ta_new_ID = env->GetFieldID(clazz, "p_td_ta_new", "J"); 1405 CHECK_EXCEPTION; 1406 1407 p_td_ta_delete_ID = env->GetFieldID(clazz, "p_td_ta_delete", "J"); 1408 CHECK_EXCEPTION; 1409 1410 p_td_ta_thr_iter_ID = env->GetFieldID(clazz, "p_td_ta_thr_iter", "J"); 1411 CHECK_EXCEPTION; 1412 1413 p_td_thr_get_info_ID = env->GetFieldID(clazz, "p_td_thr_get_info", "J"); 1414 CHECK_EXCEPTION; 1415 1416 p_td_ta_map_id2thr_ID = env->GetFieldID(clazz, "p_td_ta_map_id2thr", "J"); 1417 CHECK_EXCEPTION; 1418 1419 p_td_thr_getgregs_ID = env->GetFieldID(clazz, "p_td_thr_getgregs", "J"); 1420 CHECK_EXCEPTION; 1421 1422 getThreadForThreadId_ID = env->GetMethodID(clazz, 1423 "getThreadForThreadId", "(J)Lsun/jvm/hotspot/debugger/ThreadProxy;"); 1424 CHECK_EXCEPTION; 1425 1426 pcRegIndex_ID = env->GetFieldID(clazz, "pcRegIndex", "I"); 1427 CHECK_EXCEPTION; 1428 1429 fpRegIndex_ID = env->GetFieldID(clazz, "fpRegIndex", "I"); 1430 CHECK_EXCEPTION; 1431 1432 createSenderFrame_ID = env->GetMethodID(clazz, 1433 "createSenderFrame", "(Lsun/jvm/hotspot/debugger/proc/ProcCFrame;JJ)Lsun/jvm/hotspot/debugger/proc/ProcCFrame;"); 1434 CHECK_EXCEPTION; 1435 1436 createLoadObject_ID = env->GetMethodID(clazz, 1437 "createLoadObject", "(Ljava/lang/String;JJ)Lsun/jvm/hotspot/debugger/cdbg/LoadObject;"); 1438 CHECK_EXCEPTION; 1439 1440 createClosestSymbol_ID = env->GetMethodID(clazz, 1441 "createClosestSymbol", "(Ljava/lang/String;J)Lsun/jvm/hotspot/debugger/cdbg/ClosestSymbol;"); 1442 CHECK_EXCEPTION; 1443 1444 listAdd_ID = env->GetMethodID(env->FindClass("java/util/List"), "add", "(Ljava/lang/Object;)Z"); 1445 CHECK_EXCEPTION; 1446 1447 // part of the class sharing workaround 1448 classes_jsa_fd_ID = env->GetFieldID(clazz, "classes_jsa_fd", "I"); 1449 CHECK_EXCEPTION; 1450 p_file_map_header_ID = env->GetFieldID(clazz, "p_file_map_header", "J"); 1451 CHECK_EXCEPTION; 1452 }