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