1 /* 2 * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved. 3 * Copyright (c) 2019, 2021, NTT DATA. 4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5 * 6 * This code is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License version 2 only, as 8 * published by the Free Software Foundation. 9 * 10 * This code is distributed in the hope that it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 * version 2 for more details (a copy is included in the LICENSE file that 14 * accompanied this code). 15 * 16 * You should have received a copy of the GNU General Public License version 17 * 2 along with this work; if not, write to the Free Software Foundation, 18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 * 20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 * or visit www.oracle.com if you need additional information or have any 22 * questions. 23 * 24 */ 25 26 #include <jni.h> 27 #include "libproc.h" 28 #include "proc_service.h" 29 30 #include <elf.h> 31 #include <sys/types.h> 32 #include <sys/stat.h> 33 #include <fcntl.h> 34 #include <stdlib.h> 35 #include <string.h> 36 #include <limits.h> 37 #include <cxxabi.h> 38 39 #if defined(x86_64) && !defined(amd64) 40 #define amd64 1 41 #endif 42 43 #if defined(i386) && !defined(i586) 44 #define i586 1 45 #endif 46 47 #ifdef i586 48 #include "sun_jvm_hotspot_debugger_x86_X86ThreadContext.h" 49 #endif 50 51 #ifdef amd64 52 #include "sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext.h" 53 #endif 54 55 #if defined(ppc64) || defined(ppc64le) 56 #include "sun_jvm_hotspot_debugger_ppc64_PPC64ThreadContext.h" 57 #endif 58 59 #ifdef aarch64 60 #include "sun_jvm_hotspot_debugger_aarch64_AARCH64ThreadContext.h" 61 #endif 62 63 class AutoJavaString { 64 JNIEnv* m_env; 65 jstring m_str; 66 const char* m_buf; 67 68 public: 69 // check env->ExceptionOccurred() after ctor 70 AutoJavaString(JNIEnv* env, jstring str) 71 : m_env(env), m_str(str), m_buf(str == NULL ? NULL : env->GetStringUTFChars(str, NULL)) { 72 } 73 74 ~AutoJavaString() { 75 if (m_buf) { 76 m_env->ReleaseStringUTFChars(m_str, m_buf); 77 } 78 } 79 80 operator const char* () const { 81 return m_buf; 82 } 83 }; 84 85 static jfieldID p_ps_prochandle_ID = 0; 86 static jfieldID threadList_ID = 0; 87 static jfieldID loadObjectList_ID = 0; 88 89 static jmethodID createClosestSymbol_ID = 0; 90 static jmethodID createLoadObject_ID = 0; 91 static jmethodID getThreadForThreadId_ID = 0; 92 static jmethodID listAdd_ID = 0; 93 94 /* 95 * SA_ALTROOT environment variable. 96 * This memory holds env string for putenv(3). 97 */ 98 static char *saaltroot = NULL; 99 100 #define CHECK_EXCEPTION_(value) if (env->ExceptionOccurred()) { return value; } 101 #define CHECK_EXCEPTION if (env->ExceptionOccurred()) { return;} 102 #define THROW_NEW_DEBUGGER_EXCEPTION_(str, value) { throw_new_debugger_exception(env, str); return value; } 103 #define THROW_NEW_DEBUGGER_EXCEPTION(str) { throw_new_debugger_exception(env, str); return;} 104 105 void throw_new_debugger_exception(JNIEnv* env, const char* errMsg) { 106 jclass clazz; 107 clazz = env->FindClass("sun/jvm/hotspot/debugger/DebuggerException"); 108 CHECK_EXCEPTION; 109 env->ThrowNew(clazz, errMsg); 110 } 111 112 struct ps_prochandle* get_proc_handle(JNIEnv* env, jobject this_obj) { 113 jlong ptr = env->GetLongField(this_obj, p_ps_prochandle_ID); 114 return (struct ps_prochandle*)(intptr_t)ptr; 115 } 116 117 /* 118 * Class: sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal 119 * Method: init0 120 * Signature: ()V 121 */ 122 extern "C" 123 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal_init0 124 (JNIEnv *env, jclass cls) { 125 jclass listClass; 126 127 if (init_libproc(getenv("LIBSAPROC_DEBUG") != NULL) != true) { 128 THROW_NEW_DEBUGGER_EXCEPTION("can't initialize libproc"); 129 } 130 131 // fields we use 132 p_ps_prochandle_ID = env->GetFieldID(cls, "p_ps_prochandle", "J"); 133 CHECK_EXCEPTION; 134 threadList_ID = env->GetFieldID(cls, "threadList", "Ljava/util/List;"); 135 CHECK_EXCEPTION; 136 loadObjectList_ID = env->GetFieldID(cls, "loadObjectList", "Ljava/util/List;"); 137 CHECK_EXCEPTION; 138 139 // methods we use 140 createClosestSymbol_ID = env->GetMethodID(cls, "createClosestSymbol", 141 "(Ljava/lang/String;J)Lsun/jvm/hotspot/debugger/cdbg/ClosestSymbol;"); 142 CHECK_EXCEPTION; 143 createLoadObject_ID = env->GetMethodID(cls, "createLoadObject", 144 "(Ljava/lang/String;JJ)Lsun/jvm/hotspot/debugger/cdbg/LoadObject;"); 145 CHECK_EXCEPTION; 146 getThreadForThreadId_ID = env->GetMethodID(cls, "getThreadForThreadId", 147 "(J)Lsun/jvm/hotspot/debugger/ThreadProxy;"); 148 CHECK_EXCEPTION; 149 // java.util.List method we call 150 listClass = env->FindClass("java/util/List"); 151 CHECK_EXCEPTION; 152 listAdd_ID = env->GetMethodID(listClass, "add", "(Ljava/lang/Object;)Z"); 153 CHECK_EXCEPTION; 154 } 155 156 extern "C" 157 JNIEXPORT jint JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal_getAddressSize 158 (JNIEnv *env, jclass cls) 159 { 160 #ifdef _LP64 161 return 8; 162 #else 163 return 4; 164 #endif 165 166 } 167 168 169 static void fillThreadsAndLoadObjects(JNIEnv* env, jobject this_obj, struct ps_prochandle* ph) { 170 int n = 0, i = 0; 171 172 // add threads 173 n = get_num_threads(ph); 174 for (i = 0; i < n; i++) { 175 jobject thread; 176 jobject threadList; 177 lwpid_t lwpid; 178 179 lwpid = get_lwp_id(ph, i); 180 thread = env->CallObjectMethod(this_obj, getThreadForThreadId_ID, (jlong)lwpid); 181 CHECK_EXCEPTION; 182 threadList = env->GetObjectField(this_obj, threadList_ID); 183 CHECK_EXCEPTION; 184 env->CallBooleanMethod(threadList, listAdd_ID, thread); 185 CHECK_EXCEPTION; 186 env->DeleteLocalRef(thread); 187 env->DeleteLocalRef(threadList); 188 } 189 190 // add load objects 191 n = get_num_libs(ph); 192 for (i = 0; i < n; i++) { 193 uintptr_t base, memsz; 194 const char* name; 195 jobject loadObject; 196 jobject loadObjectList; 197 jstring str; 198 199 get_lib_addr_range(ph, i, &base, &memsz); 200 name = get_lib_name(ph, i); 201 202 str = env->NewStringUTF(name); 203 CHECK_EXCEPTION; 204 loadObject = env->CallObjectMethod(this_obj, createLoadObject_ID, str, (jlong)memsz, (jlong)base); 205 CHECK_EXCEPTION; 206 loadObjectList = env->GetObjectField(this_obj, loadObjectList_ID); 207 CHECK_EXCEPTION; 208 env->CallBooleanMethod(loadObjectList, listAdd_ID, loadObject); 209 CHECK_EXCEPTION; 210 env->DeleteLocalRef(str); 211 env->DeleteLocalRef(loadObject); 212 env->DeleteLocalRef(loadObjectList); 213 } 214 } 215 216 217 /* 218 * Verify that a named ELF binary file (core or executable) has the same 219 * bitness as ourselves. 220 * Throw an exception if there is a mismatch or other problem. 221 * 222 * If we proceed using a mismatched debugger/debuggee, the best to hope 223 * for is a missing symbol, the worst is a crash searching for debug symbols. 224 */ 225 void verifyBitness(JNIEnv *env, const char *binaryName) { 226 int fd = open(binaryName, O_RDONLY); 227 if (fd < 0) { 228 THROW_NEW_DEBUGGER_EXCEPTION("cannot open binary file"); 229 } 230 unsigned char elf_ident[EI_NIDENT]; 231 int i = read(fd, &elf_ident, sizeof(elf_ident)); 232 close(fd); 233 234 if (i < 0) { 235 THROW_NEW_DEBUGGER_EXCEPTION("cannot read binary file"); 236 } 237 #ifndef _LP64 238 if (elf_ident[EI_CLASS] == ELFCLASS64) { 239 THROW_NEW_DEBUGGER_EXCEPTION("debuggee is 64 bit, use 64-bit java for debugger"); 240 } 241 #else 242 if (elf_ident[EI_CLASS] != ELFCLASS64) { 243 THROW_NEW_DEBUGGER_EXCEPTION("debuggee is 32 bit, use 32 bit java for debugger"); 244 } 245 #endif 246 } 247 248 249 /* 250 * Class: sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal 251 * Method: setSAAltRoot0 252 * Signature: (Ljava/lang/String;)V 253 */ 254 extern "C" 255 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal_setSAAltRoot0 256 (JNIEnv *env, jobject this_obj, jstring altroot) { 257 if (saaltroot != NULL) { 258 free(saaltroot); 259 } 260 const char *path = env->GetStringUTFChars(altroot, NULL); 261 if (path == NULL) { return; } 262 /* 263 * `saaltroot` is used for putenv(). 264 * So we need to keep this memory. 265 */ 266 static const char *PREFIX = "SA_ALTROOT="; 267 size_t len = strlen(PREFIX) + strlen(path) + 1; 268 saaltroot = (char *)malloc(len); 269 snprintf(saaltroot, len, "%s%s", PREFIX, path); 270 putenv(saaltroot); 271 env->ReleaseStringUTFChars(altroot, path); 272 } 273 274 /* 275 * Class: sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal 276 * Method: attach0 277 * Signature: (I)V 278 */ 279 extern "C" 280 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal_attach0__I 281 (JNIEnv *env, jobject this_obj, jint jpid) { 282 283 // For bitness checking, locate binary at /proc/jpid/exe 284 char buf[PATH_MAX]; 285 snprintf((char *) &buf, PATH_MAX, "/proc/%d/exe", jpid); 286 verifyBitness(env, (char *) &buf); 287 CHECK_EXCEPTION; 288 289 char err_buf[200]; 290 struct ps_prochandle* ph; 291 if ((ph = Pgrab(jpid, err_buf, sizeof(err_buf))) == NULL) { 292 char msg[230]; 293 snprintf(msg, sizeof(msg), "Can't attach to the process: %s", err_buf); 294 THROW_NEW_DEBUGGER_EXCEPTION(msg); 295 } 296 env->SetLongField(this_obj, p_ps_prochandle_ID, (jlong)(intptr_t)ph); 297 fillThreadsAndLoadObjects(env, this_obj, ph); 298 } 299 300 /* 301 * Class: sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal 302 * Method: attach0 303 * Signature: (Ljava/lang/String;Ljava/lang/String;)V 304 */ 305 extern "C" 306 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal_attach0__Ljava_lang_String_2Ljava_lang_String_2 307 (JNIEnv *env, jobject this_obj, jstring execName, jstring coreName) { 308 struct ps_prochandle* ph; 309 AutoJavaString execName_cstr(env, execName); 310 CHECK_EXCEPTION; 311 AutoJavaString coreName_cstr(env, coreName); 312 CHECK_EXCEPTION; 313 314 verifyBitness(env, execName_cstr); 315 CHECK_EXCEPTION; 316 317 if ( (ph = Pgrab_core(execName_cstr, coreName_cstr)) == NULL) { 318 THROW_NEW_DEBUGGER_EXCEPTION("Can't attach to the core file"); 319 } 320 env->SetLongField(this_obj, p_ps_prochandle_ID, (jlong)(intptr_t)ph); 321 fillThreadsAndLoadObjects(env, this_obj, ph); 322 } 323 324 /* 325 * Class: sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal 326 * Method: detach0 327 * Signature: ()V 328 */ 329 extern "C" 330 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal_detach0 331 (JNIEnv *env, jobject this_obj) { 332 struct ps_prochandle* ph = get_proc_handle(env, this_obj); 333 if (ph != NULL) { 334 Prelease(ph); 335 } 336 if (saaltroot != NULL) { 337 free(saaltroot); 338 saaltroot = NULL; 339 } 340 } 341 342 /* 343 * Class: sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal 344 * Method: lookupByName0 345 * Signature: (Ljava/lang/String;Ljava/lang/String;)J 346 */ 347 extern "C" 348 JNIEXPORT jlong JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal_lookupByName0 349 (JNIEnv *env, jobject this_obj, jstring objectName, jstring symbolName) { 350 jlong addr; 351 jboolean isCopy; 352 struct ps_prochandle* ph = get_proc_handle(env, this_obj); 353 // Note, objectName is ignored, and may in fact be NULL. 354 // lookup_symbol will always search all objects/libs 355 AutoJavaString objectName_cstr(env, objectName); 356 CHECK_EXCEPTION_(0); 357 AutoJavaString symbolName_cstr(env, symbolName); 358 CHECK_EXCEPTION_(0); 359 360 addr = (jlong) lookup_symbol(ph, NULL, symbolName_cstr); 361 return addr; 362 } 363 364 /* 365 * Class: sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal 366 * Method: lookupByAddress0 367 * Signature: (J)Lsun/jvm/hotspot/debugger/cdbg/ClosestSymbol; 368 */ 369 extern "C" 370 JNIEXPORT jobject JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal_lookupByAddress0 371 (JNIEnv *env, jobject this_obj, jlong addr) { 372 uintptr_t offset; 373 jobject obj; 374 jstring str; 375 const char* sym = NULL; 376 377 struct ps_prochandle* ph = get_proc_handle(env, this_obj); 378 sym = symbol_for_pc(ph, (uintptr_t) addr, &offset); 379 if (sym == NULL) return 0; 380 str = env->NewStringUTF(sym); 381 CHECK_EXCEPTION_(NULL); 382 obj = env->CallObjectMethod(this_obj, createClosestSymbol_ID, str, (jlong)offset); 383 CHECK_EXCEPTION_(NULL); 384 return obj; 385 } 386 387 /* 388 * Class: sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal 389 * Method: readBytesFromProcess0 390 * Signature: (JJ)Lsun/jvm/hotspot/debugger/ReadResult; 391 */ 392 extern "C" 393 JNIEXPORT jbyteArray JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal_readBytesFromProcess0 394 (JNIEnv *env, jobject this_obj, jlong addr, jlong numBytes) { 395 396 jboolean isCopy; 397 jbyteArray array; 398 jbyte *bufPtr; 399 ps_err_e err; 400 401 array = env->NewByteArray(numBytes); 402 CHECK_EXCEPTION_(0); 403 bufPtr = env->GetByteArrayElements(array, &isCopy); 404 CHECK_EXCEPTION_(0); 405 406 err = ps_pdread(get_proc_handle(env, this_obj), (psaddr_t) (uintptr_t)addr, bufPtr, numBytes); 407 env->ReleaseByteArrayElements(array, bufPtr, 0); 408 return (err == PS_OK)? array : 0; 409 } 410 411 #if defined(i586) || defined(amd64) || defined(ppc64) || defined(ppc64le) || defined(aarch64) 412 extern "C" 413 JNIEXPORT jlongArray JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal_getThreadIntegerRegisterSet0 414 (JNIEnv *env, jobject this_obj, jint lwp_id) { 415 416 struct user_regs_struct gregs; 417 jboolean isCopy; 418 jlongArray array; 419 jlong *regs; 420 int i; 421 422 struct ps_prochandle* ph = get_proc_handle(env, this_obj); 423 if (get_lwp_regs(ph, lwp_id, &gregs) != true) { 424 // This is not considered fatal and does happen on occassion, usually with an 425 // ESRCH error. The root cause is not fully understood, but by ignoring this error 426 // and returning NULL, stacking walking code will get null registers and fallback 427 // to using the "last java frame" if setup. 428 fprintf(stdout, "WARNING: getThreadIntegerRegisterSet0: get_lwp_regs failed for lwp (%d)\n", lwp_id); 429 fflush(stdout); 430 return NULL; 431 } 432 433 #undef NPRGREG 434 #ifdef i586 435 #define NPRGREG sun_jvm_hotspot_debugger_x86_X86ThreadContext_NPRGREG 436 #endif 437 #ifdef amd64 438 #define NPRGREG sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_NPRGREG 439 #endif 440 #ifdef aarch64 441 #define NPRGREG sun_jvm_hotspot_debugger_aarch64_AARCH64ThreadContext_NPRGREG 442 #endif 443 #if defined(ppc64) || defined(ppc64le) 444 #define NPRGREG sun_jvm_hotspot_debugger_ppc64_PPC64ThreadContext_NPRGREG 445 #endif 446 447 448 array = env->NewLongArray(NPRGREG); 449 CHECK_EXCEPTION_(0); 450 regs = env->GetLongArrayElements(array, &isCopy); 451 452 #undef REG_INDEX 453 454 #ifdef i586 455 #define REG_INDEX(reg) sun_jvm_hotspot_debugger_x86_X86ThreadContext_##reg 456 457 regs[REG_INDEX(GS)] = (uintptr_t) gregs.xgs; 458 regs[REG_INDEX(FS)] = (uintptr_t) gregs.xfs; 459 regs[REG_INDEX(ES)] = (uintptr_t) gregs.xes; 460 regs[REG_INDEX(DS)] = (uintptr_t) gregs.xds; 461 regs[REG_INDEX(EDI)] = (uintptr_t) gregs.edi; 462 regs[REG_INDEX(ESI)] = (uintptr_t) gregs.esi; 463 regs[REG_INDEX(FP)] = (uintptr_t) gregs.ebp; 464 regs[REG_INDEX(SP)] = (uintptr_t) gregs.esp; 465 regs[REG_INDEX(EBX)] = (uintptr_t) gregs.ebx; 466 regs[REG_INDEX(EDX)] = (uintptr_t) gregs.edx; 467 regs[REG_INDEX(ECX)] = (uintptr_t) gregs.ecx; 468 regs[REG_INDEX(EAX)] = (uintptr_t) gregs.eax; 469 regs[REG_INDEX(PC)] = (uintptr_t) gregs.eip; 470 regs[REG_INDEX(CS)] = (uintptr_t) gregs.xcs; 471 regs[REG_INDEX(SS)] = (uintptr_t) gregs.xss; 472 473 #endif /* i586 */ 474 475 #ifdef amd64 476 #define REG_INDEX(reg) sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_##reg 477 478 regs[REG_INDEX(R15)] = gregs.r15; 479 regs[REG_INDEX(R14)] = gregs.r14; 480 regs[REG_INDEX(R13)] = gregs.r13; 481 regs[REG_INDEX(R12)] = gregs.r12; 482 regs[REG_INDEX(RBP)] = gregs.rbp; 483 regs[REG_INDEX(RBX)] = gregs.rbx; 484 regs[REG_INDEX(R11)] = gregs.r11; 485 regs[REG_INDEX(R10)] = gregs.r10; 486 regs[REG_INDEX(R9)] = gregs.r9; 487 regs[REG_INDEX(R8)] = gregs.r8; 488 regs[REG_INDEX(RAX)] = gregs.rax; 489 regs[REG_INDEX(RCX)] = gregs.rcx; 490 regs[REG_INDEX(RDX)] = gregs.rdx; 491 regs[REG_INDEX(RSI)] = gregs.rsi; 492 regs[REG_INDEX(RDI)] = gregs.rdi; 493 regs[REG_INDEX(RIP)] = gregs.rip; 494 regs[REG_INDEX(CS)] = gregs.cs; 495 regs[REG_INDEX(RSP)] = gregs.rsp; 496 regs[REG_INDEX(SS)] = gregs.ss; 497 regs[REG_INDEX(FSBASE)] = gregs.fs_base; 498 regs[REG_INDEX(GSBASE)] = gregs.gs_base; 499 regs[REG_INDEX(DS)] = gregs.ds; 500 regs[REG_INDEX(ES)] = gregs.es; 501 regs[REG_INDEX(FS)] = gregs.fs; 502 regs[REG_INDEX(GS)] = gregs.gs; 503 504 #endif /* amd64 */ 505 506 #if defined(aarch64) 507 508 #define REG_INDEX(reg) sun_jvm_hotspot_debugger_aarch64_AARCH64ThreadContext_##reg 509 510 { 511 int i; 512 for (i = 0; i < 31; i++) 513 regs[i] = gregs.regs[i]; 514 regs[REG_INDEX(SP)] = gregs.sp; 515 regs[REG_INDEX(PC)] = gregs.pc; 516 } 517 #endif /* aarch64 */ 518 519 #if defined(ppc64) || defined(ppc64le) 520 #define REG_INDEX(reg) sun_jvm_hotspot_debugger_ppc64_PPC64ThreadContext_##reg 521 522 regs[REG_INDEX(LR)] = gregs.link; 523 regs[REG_INDEX(NIP)] = gregs.nip; 524 regs[REG_INDEX(R0)] = gregs.gpr[0]; 525 regs[REG_INDEX(R1)] = gregs.gpr[1]; 526 regs[REG_INDEX(R2)] = gregs.gpr[2]; 527 regs[REG_INDEX(R3)] = gregs.gpr[3]; 528 regs[REG_INDEX(R4)] = gregs.gpr[4]; 529 regs[REG_INDEX(R5)] = gregs.gpr[5]; 530 regs[REG_INDEX(R6)] = gregs.gpr[6]; 531 regs[REG_INDEX(R7)] = gregs.gpr[7]; 532 regs[REG_INDEX(R8)] = gregs.gpr[8]; 533 regs[REG_INDEX(R9)] = gregs.gpr[9]; 534 regs[REG_INDEX(R10)] = gregs.gpr[10]; 535 regs[REG_INDEX(R11)] = gregs.gpr[11]; 536 regs[REG_INDEX(R12)] = gregs.gpr[12]; 537 regs[REG_INDEX(R13)] = gregs.gpr[13]; 538 regs[REG_INDEX(R14)] = gregs.gpr[14]; 539 regs[REG_INDEX(R15)] = gregs.gpr[15]; 540 regs[REG_INDEX(R16)] = gregs.gpr[16]; 541 regs[REG_INDEX(R17)] = gregs.gpr[17]; 542 regs[REG_INDEX(R18)] = gregs.gpr[18]; 543 regs[REG_INDEX(R19)] = gregs.gpr[19]; 544 regs[REG_INDEX(R20)] = gregs.gpr[20]; 545 regs[REG_INDEX(R21)] = gregs.gpr[21]; 546 regs[REG_INDEX(R22)] = gregs.gpr[22]; 547 regs[REG_INDEX(R23)] = gregs.gpr[23]; 548 regs[REG_INDEX(R24)] = gregs.gpr[24]; 549 regs[REG_INDEX(R25)] = gregs.gpr[25]; 550 regs[REG_INDEX(R26)] = gregs.gpr[26]; 551 regs[REG_INDEX(R27)] = gregs.gpr[27]; 552 regs[REG_INDEX(R28)] = gregs.gpr[28]; 553 regs[REG_INDEX(R29)] = gregs.gpr[29]; 554 regs[REG_INDEX(R30)] = gregs.gpr[30]; 555 regs[REG_INDEX(R31)] = gregs.gpr[31]; 556 557 #endif 558 559 env->ReleaseLongArrayElements(array, regs, JNI_COMMIT); 560 return array; 561 } 562 #endif 563 564 /* 565 * Class: sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal 566 * Method: demangle 567 * Signature: (Ljava/lang/String;)Ljava/lang/String; 568 */ 569 extern "C" 570 JNIEXPORT jstring JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal_demangle 571 (JNIEnv *env, jobject this_obj, jstring jsym) { 572 int status; 573 jstring result = NULL; 574 575 const char *sym = env->GetStringUTFChars(jsym, NULL); 576 if (sym == NULL) { 577 THROW_NEW_DEBUGGER_EXCEPTION_("Error getting symbol string", NULL); 578 } 579 char *demangled = abi::__cxa_demangle(sym, NULL, 0, &status); 580 env->ReleaseStringUTFChars(jsym, sym); 581 if ((demangled != NULL) && (status == 0)) { 582 result = env->NewStringUTF(demangled); 583 free(demangled); 584 } else if (status == -2) { // not C++ ABI mangling rules - maybe C style 585 result = jsym; 586 } else { 587 THROW_NEW_DEBUGGER_EXCEPTION_("Could not demangle", NULL); 588 } 589 590 return result; 591 } 592 593 /* 594 * Class: sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal 595 * Method: findLibPtrByAddress0 596 * Signature: (J)J 597 */ 598 extern "C" 599 JNIEXPORT jlong JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal_findLibPtrByAddress0 600 (JNIEnv *env, jobject this_obj, jlong pc) { 601 struct ps_prochandle* ph = get_proc_handle(env, this_obj); 602 return reinterpret_cast<jlong>(find_lib_by_address(ph, pc)); 603 }