1 /* 2 * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 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 struct ps_prochandle* ph = proc_arg_grab(cmdLine_cstr, (isProcess? PR_ARG_PIDS : PR_ARG_CORES), PGRAB_FORCE, &gcode); 759 env->ReleaseStringUTFChars(cmdLine, cmdLine_cstr); 760 if (! ph) { 761 if (gcode > 0 && gcode < sizeof(proc_arg_grab_errmsgs)/sizeof(const char*)) { 762 char errMsg[ERR_MSG_SIZE]; 763 sprintf(errMsg, "Attach failed : %s", proc_arg_grab_errmsgs[gcode]); 764 THROW_NEW_DEBUGGER_EXCEPTION(errMsg); 765 } else { 766 if (_libsaproc_debug && gcode == G_STRANGE) { 767 perror("libsaproc DEBUG: "); 768 } 769 if (isProcess) { 770 THROW_NEW_DEBUGGER_EXCEPTION("Not able to attach to process!"); 771 } else { 772 THROW_NEW_DEBUGGER_EXCEPTION("Not able to attach to core file!"); 773 } 774 } 775 } 776 777 // even though libproc.so supports 64 bit debugger and 32 bit debuggee, we don't 778 // support such cross-bit-debugging. check for that combination and throw error. 779 #ifdef _LP64 780 int data_model; 781 if (ps_pdmodel(ph, &data_model) != PS_OK) { 782 Prelease(ph, PRELEASE_CLEAR); 783 THROW_NEW_DEBUGGER_EXCEPTION("can't determine debuggee data model (ILP32? or LP64?)"); 784 } 785 if (data_model == PR_MODEL_ILP32) { 786 Prelease(ph, PRELEASE_CLEAR); 787 THROW_NEW_DEBUGGER_EXCEPTION("debuggee is 32 bit, use 32 bit java for debugger"); 788 } 789 #endif 790 791 env->SetLongField(this_obj, p_ps_prochandle_ID, (jlong)(uintptr_t)ph); 792 793 Debugger dbg; 794 dbg.env = env; 795 dbg.this_obj = this_obj; 796 jthrowable exception = 0; 797 if (! isProcess) { 798 /* 799 * With class sharing, shared perm. gen heap is allocated in with MAP_SHARED|PROT_READ. 800 * These pages are mapped from the file "classes.jsa". MAP_SHARED pages are not dumped 801 * in Solaris core.To read shared heap pages, we have to read classes.jsa file. 802 */ 803 Pobject_iter(ph, init_classsharing_workaround, &dbg); 804 exception = env->ExceptionOccurred(); 805 if (exception) { 806 env->ExceptionClear(); 807 detach_internal(env, this_obj); 808 env->Throw(exception); 809 return; 810 } 811 } 812 813 /* 814 * Iterate over the process mappings looking 815 * for libthread and then dlopen the appropriate 816 * libthread_db and get function pointers. 817 */ 818 Pobject_iter(ph, init_libthread_db_ptrs, &dbg); 819 exception = env->ExceptionOccurred(); 820 if (exception) { 821 env->ExceptionClear(); 822 if (!sa_ignore_threaddb) { 823 detach_internal(env, this_obj); 824 env->Throw(exception); 825 } 826 return; 827 } 828 829 // init libthread_db and create thread_db agent 830 p_td_init_t p_td_init = (p_td_init_t) env->GetLongField(this_obj, p_td_init_ID); 831 if (p_td_init == 0) { 832 if (!sa_ignore_threaddb) { 833 detach_internal(env, this_obj); 834 } 835 HANDLE_THREADDB_FAILURE("Did not find libthread in target process/core!"); 836 } 837 838 if (p_td_init() != TD_OK) { 839 if (!sa_ignore_threaddb) { 840 detach_internal(env, this_obj); 841 } 842 HANDLE_THREADDB_FAILURE("Can't initialize thread_db!"); 843 } 844 845 p_td_ta_new_t p_td_ta_new = (p_td_ta_new_t) env->GetLongField(this_obj, p_td_ta_new_ID); 846 847 td_thragent_t *p_td_thragent_t = 0; 848 if (p_td_ta_new(ph, &p_td_thragent_t) != TD_OK) { 849 if (!sa_ignore_threaddb) { 850 detach_internal(env, this_obj); 851 } 852 HANDLE_THREADDB_FAILURE("Can't create thread_db agent!"); 853 } 854 env->SetLongField(this_obj, p_td_thragent_t_ID, (jlong)(uintptr_t) p_td_thragent_t); 855 856 } 857 858 /* 859 * Class: sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal 860 * Method: attach0 861 * Signature: (Ljava/lang/String;)V 862 * Description: process detach 863 */ 864 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal_attach0__Ljava_lang_String_2 865 (JNIEnv *env, jobject this_obj, jstring pid) { 866 attach_internal(env, this_obj, pid, JNI_TRUE); 867 } 868 869 /* 870 * Class: sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal 871 * Method: attach0 872 * Signature: (Ljava/lang/String;Ljava/lang/String;)V 873 * Description: core file detach 874 */ 875 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal_attach0__Ljava_lang_String_2Ljava_lang_String_2 876 (JNIEnv *env, jobject this_obj, jstring executable, jstring corefile) { 877 // ignore executable file name, libproc.so can detect a.out name anyway. 878 attach_internal(env, this_obj, corefile, JNI_FALSE); 879 } 880 881 882 /* 883 * Class: sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal 884 * Method: detach0 885 * Signature: ()V 886 * Description: process/core file detach 887 */ 888 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal_detach0 889 (JNIEnv *env, jobject this_obj) { 890 detach_internal(env, this_obj); 891 } 892 893 /* 894 * Class: sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal 895 * Method: getRemoteProcessAddressSize0 896 * Signature: ()I 897 * Description: get process/core address size 898 */ 899 JNIEXPORT jint JNICALL Java_sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal_getRemoteProcessAddressSize0 900 (JNIEnv *env, jobject this_obj) { 901 jlong p_ps_prochandle; 902 p_ps_prochandle = env->GetLongField(this_obj, p_ps_prochandle_ID); 903 int data_model = PR_MODEL_ILP32; 904 ps_pdmodel((struct ps_prochandle*) p_ps_prochandle, &data_model); 905 print_debug("debuggee is %d bit\n", data_model == PR_MODEL_ILP32? 32 : 64); 906 return (jint) data_model == PR_MODEL_ILP32? 32 : 64; 907 } 908 909 /* 910 * Class: sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal 911 * Method: getPageSize0 912 * Signature: ()I 913 * Description: get process/core page size 914 */ 915 JNIEXPORT jint JNICALL Java_sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal_getPageSize0 916 (JNIEnv *env, jobject this_obj) { 917 918 /* 919 We are not yet attached to a java process or core file. getPageSize is called from 920 the constructor of ProcDebuggerLocal. The following won't work! 921 922 jlong p_ps_prochandle; 923 p_ps_prochandle = env->GetLongField(this_obj, p_ps_prochandle_ID); 924 CHECK_EXCEPTION_(-1); 925 struct ps_prochandle* prochandle = (struct ps_prochandle*) p_ps_prochandle; 926 return (Pstate(prochandle) == PS_DEAD) ? Pgetauxval(prochandle, AT_PAGESZ) 927 : getpagesize(); 928 929 So even though core may have been generated with a different page size settings, for now 930 call getpagesize. 931 */ 932 933 return getpagesize(); 934 } 935 936 /* 937 * Class: sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal 938 * Method: getThreadIntegerRegisterSet0 939 * Signature: (J)[J 940 * Description: get gregset for a given thread specified by thread id 941 */ 942 JNIEXPORT jlongArray JNICALL Java_sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal_getThreadIntegerRegisterSet0 943 (JNIEnv *env, jobject this_obj, jlong tid) { 944 // map the thread id to thread handle 945 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); 946 947 td_thragent_t* p_td_thragent_t = (td_thragent_t*) env->GetLongField(this_obj, p_td_thragent_t_ID); 948 if (p_td_thragent_t == 0) { 949 return 0; 950 } 951 952 td_thrhandle_t thr_handle; 953 if (p_td_ta_map_id2thr(p_td_thragent_t, (thread_t) tid, &thr_handle) != TD_OK) { 954 THROW_NEW_DEBUGGER_EXCEPTION_("can't map thread id to thread handle!", 0); 955 } 956 957 p_td_thr_getgregs_t p_td_thr_getgregs = (p_td_thr_getgregs_t) env->GetLongField(this_obj, p_td_thr_getgregs_ID); 958 prgregset_t gregs; 959 p_td_thr_getgregs(&thr_handle, gregs); 960 961 jlongArray res = env->NewLongArray(NPRGREG); 962 CHECK_EXCEPTION_(0); 963 jboolean isCopy; 964 jlong* ptr = env->GetLongArrayElements(res, &isCopy); 965 for (int i = 0; i < NPRGREG; i++) { 966 ptr[i] = (jlong) (uintptr_t) gregs[i]; 967 } 968 env->ReleaseLongArrayElements(res, ptr, JNI_COMMIT); 969 return res; 970 } 971 972 /* 973 * Class: sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal 974 * Method: fillThreadList0 975 * Signature: (Ljava/util/List;)V 976 * Description: fills thread list of the debuggee process/core 977 */ 978 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal_fillThreadList0 979 (JNIEnv *env, jobject this_obj, jobject list) { 980 981 td_thragent_t* p_td_thragent_t = (td_thragent_t*) env->GetLongField(this_obj, p_td_thragent_t_ID); 982 if (p_td_thragent_t == 0) { 983 return; 984 } 985 986 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); 987 988 DebuggerWithObject dbgo; 989 dbgo.env = env; 990 dbgo.this_obj = this_obj; 991 dbgo.obj = list; 992 993 p_td_ta_thr_iter(p_td_thragent_t, fill_thread_list, &dbgo, 994 TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY, TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS); 995 } 996 997 #ifndef SOLARIS_11_B159_OR_LATER 998 // building on Nevada-B158 or earlier so more hoops to jump through 999 static bool has_newer_Pstack_iter = false; // older version by default 1000 #endif 1001 1002 /* 1003 * Class: sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal 1004 * Method: fillCFrameList0 1005 * Signature: ([J)Lsun/jvm/hotspot/debugger/proc/ProcCFrame; 1006 * Description: fills CFrame list for a given thread 1007 */ 1008 JNIEXPORT jobject JNICALL Java_sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal_fillCFrameList0 1009 (JNIEnv *env, jobject this_obj, jlongArray regsArray) { 1010 jlong p_ps_prochandle = env->GetLongField(this_obj, p_ps_prochandle_ID); 1011 1012 DebuggerWith2Objects dbgo2; 1013 dbgo2.env = env; 1014 dbgo2.this_obj = this_obj; 1015 dbgo2.obj = NULL; 1016 dbgo2.obj2 = NULL; 1017 1018 jboolean isCopy; 1019 jlong* ptr = env->GetLongArrayElements(regsArray, &isCopy); 1020 CHECK_EXCEPTION_(0); 1021 1022 prgregset_t gregs; 1023 for (int i = 0; i < NPRGREG; i++) { 1024 gregs[i] = (uintptr_t) ptr[i]; 1025 } 1026 1027 env->ReleaseLongArrayElements(regsArray, ptr, JNI_ABORT); 1028 CHECK_EXCEPTION_(0); 1029 1030 #ifdef SOLARIS_11_B159_OR_LATER 1031 // building on Nevada-B159 or later so use the new callback 1032 Pstack_iter((struct ps_prochandle*) p_ps_prochandle, gregs, 1033 wrapper_fill_cframe_list, &dbgo2); 1034 #else 1035 // building on Nevada-B158 or earlier so figure out which callback to use 1036 1037 if (has_newer_Pstack_iter) { 1038 // Since we're building on Nevada-B158 or earlier, we have to 1039 // cast wrapper_fill_cframe_list to make the compiler happy. 1040 Pstack_iter((struct ps_prochandle*) p_ps_prochandle, gregs, 1041 (proc_stack_f *)wrapper_fill_cframe_list, &dbgo2); 1042 } else { 1043 Pstack_iter((struct ps_prochandle*) p_ps_prochandle, gregs, 1044 fill_cframe_list, &dbgo2); 1045 } 1046 #endif // SOLARIS_11_B159_OR_LATER 1047 return dbgo2.obj; 1048 } 1049 1050 /* 1051 * Class: sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal 1052 * Method: fillLoadObjectList0 1053 * Signature: (Ljava/util/List;)V 1054 * Description: fills shared objects of the debuggee process/core 1055 */ 1056 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal_fillLoadObjectList0 1057 (JNIEnv *env, jobject this_obj, jobject list) { 1058 DebuggerWithObject dbgo; 1059 dbgo.env = env; 1060 dbgo.this_obj = this_obj; 1061 dbgo.obj = list; 1062 1063 jlong p_ps_prochandle = env->GetLongField(this_obj, p_ps_prochandle_ID); 1064 Pobject_iter((struct ps_prochandle*) p_ps_prochandle, fill_load_object_list, &dbgo); 1065 } 1066 1067 /* 1068 * Class: sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal 1069 * Method: readBytesFromProcess0 1070 * Signature: (JJ)[B 1071 * Description: read bytes from debuggee process/core 1072 */ 1073 JNIEXPORT jbyteArray JNICALL Java_sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal_readBytesFromProcess0 1074 (JNIEnv *env, jobject this_obj, jlong address, jlong numBytes) { 1075 1076 jbyteArray array = env->NewByteArray(numBytes); 1077 CHECK_EXCEPTION_(0); 1078 jboolean isCopy; 1079 jbyte* bufPtr = env->GetByteArrayElements(array, &isCopy); 1080 CHECK_EXCEPTION_(0); 1081 1082 jlong p_ps_prochandle = env->GetLongField(this_obj, p_ps_prochandle_ID); 1083 ps_err_e ret = ps_pread((struct ps_prochandle*) p_ps_prochandle, 1084 (psaddr_t)address, bufPtr, (size_t)numBytes); 1085 1086 if (ret != PS_OK) { 1087 // part of the class sharing workaround. try shared heap area 1088 int classes_jsa_fd = env->GetIntField(this_obj, classes_jsa_fd_ID); 1089 if (classes_jsa_fd != -1 && address != (jlong)0) { 1090 print_debug("read failed at 0x%lx, attempting shared heap area\n", (long) address); 1091 1092 struct FileMapHeader* pheader = (struct FileMapHeader*) env->GetLongField(this_obj, p_file_map_header_ID); 1093 // walk through the shared mappings -- we just have 4 of them. 1094 // so, linear walking is okay. 1095 for (int m = 0; m < NUM_SHARED_MAPS; m++) { 1096 1097 // We can skip the non-read-only maps. These are mapped as MAP_PRIVATE 1098 // and hence will be read by libproc. Besides, the file copy may be 1099 // stale because the process might have modified those pages. 1100 if (pheader->_space[m]._read_only) { 1101 jlong baseAddress = (jlong) (uintptr_t) pheader->_space[m]._base; 1102 size_t usedSize = pheader->_space[m]._used; 1103 if (address >= baseAddress && address < (baseAddress + usedSize)) { 1104 // the given address falls in this shared heap area 1105 print_debug("found shared map at 0x%lx\n", (long) baseAddress); 1106 1107 1108 // If more data is asked than actually mapped from file, we need to zero fill 1109 // till the end-of-page boundary. But, java array new does that for us. we just 1110 // need to read as much as data available. 1111 1112 #define MIN2(x, y) (((x) < (y))? (x) : (y)) 1113 1114 jlong diff = address - baseAddress; 1115 jlong bytesToRead = MIN2(numBytes, usedSize - diff); 1116 off_t offset = pheader->_space[m]._file_offset + off_t(diff); 1117 ssize_t bytesRead = pread(classes_jsa_fd, bufPtr, bytesToRead, offset); 1118 if (bytesRead != bytesToRead) { 1119 env->ReleaseByteArrayElements(array, bufPtr, JNI_ABORT); 1120 print_debug("shared map read failed\n"); 1121 return jbyteArray(0); 1122 } else { 1123 print_debug("shared map read succeeded\n"); 1124 env->ReleaseByteArrayElements(array, bufPtr, 0); 1125 return array; 1126 } 1127 } // is in current map 1128 } // is read only map 1129 } // for shared maps 1130 } // classes_jsa_fd != -1 1131 env->ReleaseByteArrayElements(array, bufPtr, JNI_ABORT); 1132 return jbyteArray(0); 1133 } else { 1134 env->ReleaseByteArrayElements(array, bufPtr, 0); 1135 return array; 1136 } 1137 } 1138 1139 /* 1140 * Class: sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal 1141 * Method: writeBytesToProcess0 1142 * Signature: (JJ[B)V 1143 * Description: write bytes into debugger process 1144 */ 1145 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal_writeBytesToProcess0 1146 (JNIEnv *env, jobject this_obj, jlong address, jlong numBytes, jbyteArray data) { 1147 jlong p_ps_prochandle = env->GetLongField(this_obj, p_ps_prochandle_ID); 1148 jboolean isCopy; 1149 jbyte* ptr = env->GetByteArrayElements(data, &isCopy); 1150 CHECK_EXCEPTION; 1151 1152 if (ps_pwrite((struct ps_prochandle*) p_ps_prochandle, address, ptr, numBytes) != PS_OK) { 1153 env->ReleaseByteArrayElements(data, ptr, JNI_ABORT); 1154 THROW_NEW_DEBUGGER_EXCEPTION("Process write failed!"); 1155 } 1156 1157 env->ReleaseByteArrayElements(data, ptr, JNI_ABORT); 1158 } 1159 1160 /* 1161 * Class: sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal 1162 * Method: suspend0 1163 * Signature: ()V 1164 */ 1165 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal_suspend0 1166 (JNIEnv *env, jobject this_obj) { 1167 jlong p_ps_prochandle = env->GetLongField(this_obj, p_ps_prochandle_ID); 1168 // for now don't check return value. revisit this again. 1169 Pstop((struct ps_prochandle*) p_ps_prochandle, 1000); 1170 } 1171 1172 /* 1173 * Class: sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal 1174 * Method: resume0 1175 * Signature: ()V 1176 */ 1177 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal_resume0 1178 (JNIEnv *env, jobject this_obj) { 1179 jlong p_ps_prochandle = env->GetLongField(this_obj, p_ps_prochandle_ID); 1180 // for now don't check return value. revisit this again. 1181 Psetrun((struct ps_prochandle*) p_ps_prochandle, 0, PRCFAULT|PRSTOP); 1182 } 1183 1184 /* 1185 * Class: sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal 1186 * Method: lookupByName0 1187 * Signature: (Ljava/lang/String;Ljava/lang/String;)J 1188 * Description: symbol lookup by name 1189 */ 1190 JNIEXPORT jlong JNICALL Java_sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal_lookupByName0 1191 (JNIEnv *env, jobject this_obj, jstring objectName, jstring symbolName) { 1192 jlong p_ps_prochandle; 1193 p_ps_prochandle = env->GetLongField(this_obj, p_ps_prochandle_ID); 1194 1195 jboolean isCopy; 1196 const char* objectName_cstr = NULL; 1197 if (objectName != NULL) { 1198 objectName_cstr = env->GetStringUTFChars(objectName, &isCopy); 1199 CHECK_EXCEPTION_(0); 1200 } else { 1201 objectName_cstr = PR_OBJ_EVERY; 1202 } 1203 1204 const char* symbolName_cstr = env->GetStringUTFChars(symbolName, &isCopy); 1205 CHECK_EXCEPTION_(0); 1206 1207 psaddr_t symbol_addr = (psaddr_t) 0; 1208 ps_pglobal_lookup((struct ps_prochandle*) p_ps_prochandle, objectName_cstr, 1209 symbolName_cstr, &symbol_addr); 1210 1211 if (symbol_addr == 0) { 1212 print_debug("lookup for %s in %s failed\n", symbolName_cstr, objectName_cstr); 1213 } 1214 1215 if (objectName_cstr != PR_OBJ_EVERY) { 1216 env->ReleaseStringUTFChars(objectName, objectName_cstr); 1217 } 1218 env->ReleaseStringUTFChars(symbolName, symbolName_cstr); 1219 return (jlong) (uintptr_t) symbol_addr; 1220 } 1221 1222 /* 1223 * Class: sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal 1224 * Method: lookupByAddress0 1225 * Signature: (J)Lsun/jvm/hotspot/debugger/cdbg/ClosestSymbol; 1226 * Description: lookup symbol name for a given address 1227 */ 1228 JNIEXPORT jobject JNICALL Java_sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal_lookupByAddress0 1229 (JNIEnv *env, jobject this_obj, jlong address) { 1230 jlong p_ps_prochandle; 1231 p_ps_prochandle = env->GetLongField(this_obj, p_ps_prochandle_ID); 1232 1233 char nameBuf[SYMBOL_BUF_SIZE + 1]; 1234 GElf_Sym sym; 1235 int res = Plookup_by_addr((struct ps_prochandle*) p_ps_prochandle, (uintptr_t) address, 1236 nameBuf, sizeof(nameBuf), &sym); 1237 if (res != 0) { // failed 1238 return 0; 1239 } 1240 1241 jstring resSym = env->NewStringUTF(nameBuf); 1242 CHECK_EXCEPTION_(0); 1243 1244 return env->CallObjectMethod(this_obj, createClosestSymbol_ID, resSym, (address - sym.st_value)); 1245 } 1246 1247 /* 1248 * Class: sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal 1249 * Method: demangle0 1250 * Signature: (Ljava/lang/String;)Ljava/lang/String; 1251 */ 1252 JNIEXPORT jstring JNICALL Java_sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal_demangle0 1253 (JNIEnv *env, jobject this_object, jstring name) { 1254 jboolean isCopy; 1255 const char* ptr = env->GetStringUTFChars(name, &isCopy); 1256 char buf[2*SYMBOL_BUF_SIZE + 1]; 1257 jstring res = 0; 1258 if (cplus_demangle((char*) ptr, buf, sizeof(buf)) != DEMANGLE_ESPACE) { 1259 res = env->NewStringUTF(buf); 1260 } else { 1261 res = name; 1262 } 1263 env->ReleaseStringUTFChars(name, ptr); 1264 return res; 1265 } 1266 1267 #ifndef SOLARIS_11_B159_OR_LATER 1268 // Determine if the OS we're running on has the newer version 1269 // of libproc's Pstack_iter. 1270 // 1271 // Set env var PSTACK_ITER_DEBUG=true to debug this logic. 1272 // Set env var PSTACK_ITER_DEBUG_RELEASE to simulate a 'release' value. 1273 // Set env var PSTACK_ITER_DEBUG_VERSION to simulate a 'version' value. 1274 // 1275 // frankenputer 'uname -r -v': 5.10 Generic_141445-09 1276 // jurassic 'uname -r -v': 5.11 snv_164 1277 // lonepeak 'uname -r -v': 5.11 snv_127 1278 // 1279 static void set_has_newer_Pstack_iter(JNIEnv *env) { 1280 static bool done_set = false; 1281 1282 if (done_set) { 1283 // already set has_newer_Pstack_iter 1284 return; 1285 } 1286 1287 struct utsname name; 1288 if (uname(&name) == -1) { 1289 THROW_NEW_DEBUGGER_EXCEPTION("uname() failed!"); 1290 } 1291 dprintf_2("release='%s' version='%s'\n", name.release, name.version); 1292 1293 if (_Pstack_iter_debug) { 1294 char *override = getenv("PSTACK_ITER_DEBUG_RELEASE"); 1295 if (override != NULL) { 1296 strncpy(name.release, override, SYS_NMLN - 1); 1297 name.release[SYS_NMLN - 2] = '\0'; 1298 dprintf_2("overriding with release='%s'\n", name.release); 1299 } 1300 override = getenv("PSTACK_ITER_DEBUG_VERSION"); 1301 if (override != NULL) { 1302 strncpy(name.version, override, SYS_NMLN - 1); 1303 name.version[SYS_NMLN - 2] = '\0'; 1304 dprintf_2("overriding with version='%s'\n", name.version); 1305 } 1306 } 1307 1308 // the major number corresponds to the old SunOS major number 1309 int major = atoi(name.release); 1310 if (major >= 6) { 1311 dprintf_2("release is SunOS 6 or later\n"); 1312 has_newer_Pstack_iter = true; 1313 done_set = true; 1314 return; 1315 } 1316 if (major < 5) { 1317 dprintf_2("release is SunOS 4 or earlier\n"); 1318 done_set = true; 1319 return; 1320 } 1321 1322 // some SunOS 5.* build so now check for Solaris versions 1323 char *dot = strchr(name.release, '.'); 1324 int minor = 0; 1325 if (dot != NULL) { 1326 // release is major.minor format 1327 *dot = NULL; 1328 minor = atoi(dot + 1); 1329 } 1330 1331 if (minor <= 10) { 1332 dprintf_2("release is Solaris 10 or earlier\n"); 1333 done_set = true; 1334 return; 1335 } else if (minor >= 12) { 1336 dprintf_2("release is Solaris 12 or later\n"); 1337 has_newer_Pstack_iter = true; 1338 done_set = true; 1339 return; 1340 } 1341 1342 // some Solaris 11 build so now check for internal build numbers 1343 if (strncmp(name.version, "snv_", 4) != 0) { 1344 dprintf_2("release is Solaris 11 post-GA or later\n"); 1345 has_newer_Pstack_iter = true; 1346 done_set = true; 1347 return; 1348 } 1349 1350 // version begins with "snv_" so a pre-GA build of Solaris 11 1351 int build = atoi(&name.version[4]); 1352 if (build >= 159) { 1353 dprintf_2("release is Nevada-B159 or later\n"); 1354 has_newer_Pstack_iter = true; 1355 } else { 1356 dprintf_2("release is Nevada-B158 or earlier\n"); 1357 } 1358 1359 done_set = true; 1360 } 1361 #endif // !SOLARIS_11_B159_OR_LATER 1362 1363 /* 1364 * Class: sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal 1365 * Method: initIDs 1366 * Signature: ()V 1367 * Description: get JNI ids for fields and methods of ProcDebuggerLocal class 1368 */ 1369 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal_initIDs 1370 (JNIEnv *env, jclass clazz) { 1371 _libsaproc_debug = getenv("LIBSAPROC_DEBUG") != NULL; 1372 if (_libsaproc_debug) { 1373 // propagate debug mode to libproc.so 1374 static const char* var = "LIBPROC_DEBUG=1"; 1375 putenv((char*)var); 1376 } 1377 1378 void* libproc_handle = dlopen("libproc.so", RTLD_LAZY | RTLD_GLOBAL); 1379 if (libproc_handle == 0) 1380 THROW_NEW_DEBUGGER_EXCEPTION("can't load libproc.so, if you are using Solaris 5.7 or below, copy libproc.so from 5.8!"); 1381 1382 #ifndef SOLARIS_11_B159_OR_LATER 1383 _Pstack_iter_debug = getenv("PSTACK_ITER_DEBUG") != NULL; 1384 1385 set_has_newer_Pstack_iter(env); 1386 CHECK_EXCEPTION; 1387 dprintf_2("has_newer_Pstack_iter=%d\n", has_newer_Pstack_iter); 1388 #endif 1389 1390 p_ps_prochandle_ID = env->GetFieldID(clazz, "p_ps_prochandle", "J"); 1391 CHECK_EXCEPTION; 1392 1393 libthread_db_handle_ID = env->GetFieldID(clazz, "libthread_db_handle", "J"); 1394 CHECK_EXCEPTION; 1395 1396 p_td_thragent_t_ID = env->GetFieldID(clazz, "p_td_thragent_t", "J"); 1397 CHECK_EXCEPTION; 1398 1399 p_td_init_ID = env->GetFieldID(clazz, "p_td_init", "J"); 1400 CHECK_EXCEPTION; 1401 1402 p_td_ta_new_ID = env->GetFieldID(clazz, "p_td_ta_new", "J"); 1403 CHECK_EXCEPTION; 1404 1405 p_td_ta_delete_ID = env->GetFieldID(clazz, "p_td_ta_delete", "J"); 1406 CHECK_EXCEPTION; 1407 1408 p_td_ta_thr_iter_ID = env->GetFieldID(clazz, "p_td_ta_thr_iter", "J"); 1409 CHECK_EXCEPTION; 1410 1411 p_td_thr_get_info_ID = env->GetFieldID(clazz, "p_td_thr_get_info", "J"); 1412 CHECK_EXCEPTION; 1413 1414 p_td_ta_map_id2thr_ID = env->GetFieldID(clazz, "p_td_ta_map_id2thr", "J"); 1415 CHECK_EXCEPTION; 1416 1417 p_td_thr_getgregs_ID = env->GetFieldID(clazz, "p_td_thr_getgregs", "J"); 1418 CHECK_EXCEPTION; 1419 1420 getThreadForThreadId_ID = env->GetMethodID(clazz, 1421 "getThreadForThreadId", "(J)Lsun/jvm/hotspot/debugger/ThreadProxy;"); 1422 CHECK_EXCEPTION; 1423 1424 pcRegIndex_ID = env->GetFieldID(clazz, "pcRegIndex", "I"); 1425 CHECK_EXCEPTION; 1426 1427 fpRegIndex_ID = env->GetFieldID(clazz, "fpRegIndex", "I"); 1428 CHECK_EXCEPTION; 1429 1430 createSenderFrame_ID = env->GetMethodID(clazz, 1431 "createSenderFrame", "(Lsun/jvm/hotspot/debugger/proc/ProcCFrame;JJ)Lsun/jvm/hotspot/debugger/proc/ProcCFrame;"); 1432 CHECK_EXCEPTION; 1433 1434 createLoadObject_ID = env->GetMethodID(clazz, 1435 "createLoadObject", "(Ljava/lang/String;JJ)Lsun/jvm/hotspot/debugger/cdbg/LoadObject;"); 1436 CHECK_EXCEPTION; 1437 1438 createClosestSymbol_ID = env->GetMethodID(clazz, 1439 "createClosestSymbol", "(Ljava/lang/String;J)Lsun/jvm/hotspot/debugger/cdbg/ClosestSymbol;"); 1440 CHECK_EXCEPTION; 1441 1442 listAdd_ID = env->GetMethodID(env->FindClass("java/util/List"), "add", "(Ljava/lang/Object;)Z"); 1443 CHECK_EXCEPTION; 1444 1445 // part of the class sharing workaround 1446 classes_jsa_fd_ID = env->GetFieldID(clazz, "classes_jsa_fd", "I"); 1447 CHECK_EXCEPTION; 1448 p_file_map_header_ID = env->GetFieldID(clazz, "p_file_map_header", "J"); 1449 CHECK_EXCEPTION; 1450 }