1 /* 2 * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. 3 * Copyright (c) 2019, 2020, 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(sparc) || defined(sparcv9) 56 #include "sun_jvm_hotspot_debugger_sparc_SPARCThreadContext.h" 57 #endif 58 59 #if defined(ppc64) || defined(ppc64le) 60 #include "sun_jvm_hotspot_debugger_ppc64_PPC64ThreadContext.h" 61 #endif 62 63 #ifdef aarch64 64 #include "sun_jvm_hotspot_debugger_aarch64_AARCH64ThreadContext.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(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 } 191 192 // add load objects 193 n = get_num_libs(ph); 194 for (i = 0; i < n; i++) { 195 uintptr_t base; 196 const char* name; 197 jobject loadObject; 198 jobject loadObjectList; 199 jstring str; 200 201 base = get_lib_base(ph, i); 202 name = get_lib_name(ph, i); 203 204 str = env->NewStringUTF(name); 205 CHECK_EXCEPTION; 206 loadObject = env->CallObjectMethod(this_obj, createLoadObject_ID, str, (jlong)0, (jlong)base); 207 CHECK_EXCEPTION; 208 loadObjectList = env->GetObjectField(this_obj, loadObjectList_ID); 209 CHECK_EXCEPTION; 210 env->CallBooleanMethod(loadObjectList, listAdd_ID, loadObject); 211 CHECK_EXCEPTION; 212 } 213 } 214 215 216 /* 217 * Verify that a named ELF binary file (core or executable) has the same 218 * bitness as ourselves. 219 * Throw an exception if there is a mismatch or other problem. 220 * 221 * If we proceed using a mismatched debugger/debuggee, the best to hope 222 * for is a missing symbol, the worst is a crash searching for debug symbols. 223 */ 224 void verifyBitness(JNIEnv *env, const char *binaryName) { 225 int fd = open(binaryName, O_RDONLY); 226 if (fd < 0) { 227 THROW_NEW_DEBUGGER_EXCEPTION("cannot open binary file"); 228 } 229 unsigned char elf_ident[EI_NIDENT]; 230 int i = read(fd, &elf_ident, sizeof(elf_ident)); 231 close(fd); 232 233 if (i < 0) { 234 THROW_NEW_DEBUGGER_EXCEPTION("cannot read binary file"); 235 } 236 #ifndef _LP64 237 if (elf_ident[EI_CLASS] == ELFCLASS64) { 238 THROW_NEW_DEBUGGER_EXCEPTION("debuggee is 64 bit, use 64-bit java for debugger"); 239 } 240 #else 241 if (elf_ident[EI_CLASS] != ELFCLASS64) { 242 THROW_NEW_DEBUGGER_EXCEPTION("debuggee is 32 bit, use 32 bit java for debugger"); 243 } 244 #endif 245 } 246 247 248 /* 249 * Class: sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal 250 * Method: setSAAltRoot0 251 * Signature: (Ljava/lang/String;)V 252 */ 253 extern "C" 254 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal_setSAAltRoot0 255 (JNIEnv *env, jobject this_obj, jstring altroot) { 256 if (saaltroot != NULL) { 257 free(saaltroot); 258 } 259 const char *path = env->GetStringUTFChars(altroot, NULL); 260 if (path == NULL) { return; } 261 /* 262 * `saaltroot` is used for putenv(). 263 * So we need to keep this memory. 264 */ 265 static const char *PREFIX = "SA_ALTROOT="; 266 size_t len = strlen(PREFIX) + strlen(path) + 1; 267 saaltroot = (char *)malloc(len); 268 snprintf(saaltroot, len, "%s%s", PREFIX, path); 269 putenv(saaltroot); 270 env->ReleaseStringUTFChars(altroot, path); 271 } 272 273 /* 274 * Class: sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal 275 * Method: attach0 276 * Signature: (I)V 277 */ 278 extern "C" 279 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal_attach0__I 280 (JNIEnv *env, jobject this_obj, jint jpid) { 281 282 // For bitness checking, locate binary at /proc/jpid/exe 283 char buf[PATH_MAX]; 284 snprintf((char *) &buf, PATH_MAX, "/proc/%d/exe", jpid); 285 verifyBitness(env, (char *) &buf); 286 CHECK_EXCEPTION; 287 288 char err_buf[200]; 289 struct ps_prochandle* ph; 290 if ((ph = Pgrab(jpid, err_buf, sizeof(err_buf))) == NULL) { 291 char msg[230]; 292 snprintf(msg, sizeof(msg), "Can't attach to the process: %s", err_buf); 293 THROW_NEW_DEBUGGER_EXCEPTION(msg); 294 } 295 env->SetLongField(this_obj, p_ps_prochandle_ID, (jlong)(intptr_t)ph); 296 fillThreadsAndLoadObjects(env, this_obj, ph); 297 } 298 299 /* 300 * Class: sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal 301 * Method: attach0 302 * Signature: (Ljava/lang/String;Ljava/lang/String;)V 303 */ 304 extern "C" 305 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal_attach0__Ljava_lang_String_2Ljava_lang_String_2 306 (JNIEnv *env, jobject this_obj, jstring execName, jstring coreName) { 307 struct ps_prochandle* ph; 308 AutoJavaString execName_cstr(env, execName); 309 CHECK_EXCEPTION; 310 AutoJavaString coreName_cstr(env, coreName); 311 CHECK_EXCEPTION; 312 313 verifyBitness(env, execName_cstr); 314 CHECK_EXCEPTION; 315 316 if ( (ph = Pgrab_core(execName_cstr, coreName_cstr)) == NULL) { 317 THROW_NEW_DEBUGGER_EXCEPTION("Can't attach to the core file"); 318 } 319 env->SetLongField(this_obj, p_ps_prochandle_ID, (jlong)(intptr_t)ph); 320 fillThreadsAndLoadObjects(env, this_obj, ph); 321 } 322 323 /* 324 * Class: sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal 325 * Method: detach0 326 * Signature: ()V 327 */ 328 extern "C" 329 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal_detach0 330 (JNIEnv *env, jobject this_obj) { 331 struct ps_prochandle* ph = get_proc_handle(env, this_obj); 332 if (ph != NULL) { 333 Prelease(ph); 334 } 335 if (saaltroot != NULL) { 336 free(saaltroot); 337 saaltroot = NULL; 338 } 339 } 340 341 /* 342 * Class: sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal 343 * Method: lookupByName0 344 * Signature: (Ljava/lang/String;Ljava/lang/String;)J 345 */ 346 extern "C" 347 JNIEXPORT jlong JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal_lookupByName0 348 (JNIEnv *env, jobject this_obj, jstring objectName, jstring symbolName) { 349 jlong addr; 350 jboolean isCopy; 351 struct ps_prochandle* ph = get_proc_handle(env, this_obj); 352 AutoJavaString objectName_cstr(env, objectName); 353 CHECK_EXCEPTION_(0); 354 AutoJavaString symbolName_cstr(env, symbolName); 355 CHECK_EXCEPTION_(0); 356 357 addr = (jlong) lookup_symbol(ph, objectName_cstr, symbolName_cstr); 358 return addr; 359 } 360 361 /* 362 * Class: sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal 363 * Method: lookupByAddress0 364 * Signature: (J)Lsun/jvm/hotspot/debugger/cdbg/ClosestSymbol; 365 */ 366 extern "C" 367 JNIEXPORT jobject JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal_lookupByAddress0 368 (JNIEnv *env, jobject this_obj, jlong addr) { 369 uintptr_t offset; 370 jobject obj; 371 jstring str; 372 const char* sym = NULL; 373 374 struct ps_prochandle* ph = get_proc_handle(env, this_obj); 375 sym = symbol_for_pc(ph, (uintptr_t) addr, &offset); 376 if (sym == NULL) return 0; 377 str = env->NewStringUTF(sym); 378 CHECK_EXCEPTION_(NULL); 379 obj = env->CallObjectMethod(this_obj, createClosestSymbol_ID, str, (jlong)offset); 380 CHECK_EXCEPTION_(NULL); 381 return obj; 382 } 383 384 /* 385 * Class: sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal 386 * Method: readBytesFromProcess0 387 * Signature: (JJ)Lsun/jvm/hotspot/debugger/ReadResult; 388 */ 389 extern "C" 390 JNIEXPORT jbyteArray JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal_readBytesFromProcess0 391 (JNIEnv *env, jobject this_obj, jlong addr, jlong numBytes) { 392 393 jboolean isCopy; 394 jbyteArray array; 395 jbyte *bufPtr; 396 ps_err_e err; 397 398 array = env->NewByteArray(numBytes); 399 CHECK_EXCEPTION_(0); 400 bufPtr = env->GetByteArrayElements(array, &isCopy); 401 CHECK_EXCEPTION_(0); 402 403 err = ps_pdread(get_proc_handle(env, this_obj), (psaddr_t) (uintptr_t)addr, bufPtr, numBytes); 404 env->ReleaseByteArrayElements(array, bufPtr, 0); 405 return (err == PS_OK)? array : 0; 406 } 407 408 #if defined(i586) || defined(amd64) || defined(sparc) || defined(sparcv9) | defined(ppc64) || defined(ppc64le) || defined(aarch64) 409 extern "C" 410 JNIEXPORT jlongArray JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal_getThreadIntegerRegisterSet0 411 (JNIEnv *env, jobject this_obj, jint lwp_id) { 412 413 struct user_regs_struct gregs; 414 jboolean isCopy; 415 jlongArray array; 416 jlong *regs; 417 int i; 418 419 struct ps_prochandle* ph = get_proc_handle(env, this_obj); 420 if (get_lwp_regs(ph, lwp_id, &gregs) != true) { 421 THROW_NEW_DEBUGGER_EXCEPTION_("get_thread_regs failed for a lwp", 0); 422 } 423 424 #undef NPRGREG 425 #ifdef i586 426 #define NPRGREG sun_jvm_hotspot_debugger_x86_X86ThreadContext_NPRGREG 427 #endif 428 #ifdef amd64 429 #define NPRGREG sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_NPRGREG 430 #endif 431 #ifdef aarch64 432 #define NPRGREG sun_jvm_hotspot_debugger_aarch64_AARCH64ThreadContext_NPRGREG 433 #endif 434 #if defined(sparc) || defined(sparcv9) 435 #define NPRGREG sun_jvm_hotspot_debugger_sparc_SPARCThreadContext_NPRGREG 436 #endif 437 #if defined(ppc64) || defined(ppc64le) 438 #define NPRGREG sun_jvm_hotspot_debugger_ppc64_PPC64ThreadContext_NPRGREG 439 #endif 440 441 442 array = env->NewLongArray(NPRGREG); 443 CHECK_EXCEPTION_(0); 444 regs = env->GetLongArrayElements(array, &isCopy); 445 446 #undef REG_INDEX 447 448 #ifdef i586 449 #define REG_INDEX(reg) sun_jvm_hotspot_debugger_x86_X86ThreadContext_##reg 450 451 regs[REG_INDEX(GS)] = (uintptr_t) gregs.xgs; 452 regs[REG_INDEX(FS)] = (uintptr_t) gregs.xfs; 453 regs[REG_INDEX(ES)] = (uintptr_t) gregs.xes; 454 regs[REG_INDEX(DS)] = (uintptr_t) gregs.xds; 455 regs[REG_INDEX(EDI)] = (uintptr_t) gregs.edi; 456 regs[REG_INDEX(ESI)] = (uintptr_t) gregs.esi; 457 regs[REG_INDEX(FP)] = (uintptr_t) gregs.ebp; 458 regs[REG_INDEX(SP)] = (uintptr_t) gregs.esp; 459 regs[REG_INDEX(EBX)] = (uintptr_t) gregs.ebx; 460 regs[REG_INDEX(EDX)] = (uintptr_t) gregs.edx; 461 regs[REG_INDEX(ECX)] = (uintptr_t) gregs.ecx; 462 regs[REG_INDEX(EAX)] = (uintptr_t) gregs.eax; 463 regs[REG_INDEX(PC)] = (uintptr_t) gregs.eip; 464 regs[REG_INDEX(CS)] = (uintptr_t) gregs.xcs; 465 regs[REG_INDEX(SS)] = (uintptr_t) gregs.xss; 466 467 #endif /* i586 */ 468 469 #ifdef amd64 470 #define REG_INDEX(reg) sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_##reg 471 472 regs[REG_INDEX(R15)] = gregs.r15; 473 regs[REG_INDEX(R14)] = gregs.r14; 474 regs[REG_INDEX(R13)] = gregs.r13; 475 regs[REG_INDEX(R12)] = gregs.r12; 476 regs[REG_INDEX(RBP)] = gregs.rbp; 477 regs[REG_INDEX(RBX)] = gregs.rbx; 478 regs[REG_INDEX(R11)] = gregs.r11; 479 regs[REG_INDEX(R10)] = gregs.r10; 480 regs[REG_INDEX(R9)] = gregs.r9; 481 regs[REG_INDEX(R8)] = gregs.r8; 482 regs[REG_INDEX(RAX)] = gregs.rax; 483 regs[REG_INDEX(RCX)] = gregs.rcx; 484 regs[REG_INDEX(RDX)] = gregs.rdx; 485 regs[REG_INDEX(RSI)] = gregs.rsi; 486 regs[REG_INDEX(RDI)] = gregs.rdi; 487 regs[REG_INDEX(RIP)] = gregs.rip; 488 regs[REG_INDEX(CS)] = gregs.cs; 489 regs[REG_INDEX(RSP)] = gregs.rsp; 490 regs[REG_INDEX(SS)] = gregs.ss; 491 regs[REG_INDEX(FSBASE)] = gregs.fs_base; 492 regs[REG_INDEX(GSBASE)] = gregs.gs_base; 493 regs[REG_INDEX(DS)] = gregs.ds; 494 regs[REG_INDEX(ES)] = gregs.es; 495 regs[REG_INDEX(FS)] = gregs.fs; 496 regs[REG_INDEX(GS)] = gregs.gs; 497 498 #endif /* amd64 */ 499 500 #if defined(sparc) || defined(sparcv9) 501 502 #define REG_INDEX(reg) sun_jvm_hotspot_debugger_sparc_SPARCThreadContext_##reg 503 504 #ifdef _LP64 505 regs[REG_INDEX(R_PSR)] = gregs.tstate; 506 regs[REG_INDEX(R_PC)] = gregs.tpc; 507 regs[REG_INDEX(R_nPC)] = gregs.tnpc; 508 regs[REG_INDEX(R_Y)] = gregs.y; 509 #else 510 regs[REG_INDEX(R_PSR)] = gregs.psr; 511 regs[REG_INDEX(R_PC)] = gregs.pc; 512 regs[REG_INDEX(R_nPC)] = gregs.npc; 513 regs[REG_INDEX(R_Y)] = gregs.y; 514 #endif 515 regs[REG_INDEX(R_G0)] = 0 ; 516 regs[REG_INDEX(R_G1)] = gregs.u_regs[0]; 517 regs[REG_INDEX(R_G2)] = gregs.u_regs[1]; 518 regs[REG_INDEX(R_G3)] = gregs.u_regs[2]; 519 regs[REG_INDEX(R_G4)] = gregs.u_regs[3]; 520 regs[REG_INDEX(R_G5)] = gregs.u_regs[4]; 521 regs[REG_INDEX(R_G6)] = gregs.u_regs[5]; 522 regs[REG_INDEX(R_G7)] = gregs.u_regs[6]; 523 regs[REG_INDEX(R_O0)] = gregs.u_regs[7]; 524 regs[REG_INDEX(R_O1)] = gregs.u_regs[8]; 525 regs[REG_INDEX(R_O2)] = gregs.u_regs[ 9]; 526 regs[REG_INDEX(R_O3)] = gregs.u_regs[10]; 527 regs[REG_INDEX(R_O4)] = gregs.u_regs[11]; 528 regs[REG_INDEX(R_O5)] = gregs.u_regs[12]; 529 regs[REG_INDEX(R_O6)] = gregs.u_regs[13]; 530 regs[REG_INDEX(R_O7)] = gregs.u_regs[14]; 531 #endif /* sparc */ 532 533 #if defined(aarch64) 534 535 #define REG_INDEX(reg) sun_jvm_hotspot_debugger_aarch64_AARCH64ThreadContext_##reg 536 537 { 538 int i; 539 for (i = 0; i < 31; i++) 540 regs[i] = gregs.regs[i]; 541 regs[REG_INDEX(SP)] = gregs.sp; 542 regs[REG_INDEX(PC)] = gregs.pc; 543 } 544 #endif /* aarch64 */ 545 546 #if defined(ppc64) || defined(ppc64le) 547 #define REG_INDEX(reg) sun_jvm_hotspot_debugger_ppc64_PPC64ThreadContext_##reg 548 549 regs[REG_INDEX(LR)] = gregs.link; 550 regs[REG_INDEX(NIP)] = gregs.nip; 551 regs[REG_INDEX(R0)] = gregs.gpr[0]; 552 regs[REG_INDEX(R1)] = gregs.gpr[1]; 553 regs[REG_INDEX(R2)] = gregs.gpr[2]; 554 regs[REG_INDEX(R3)] = gregs.gpr[3]; 555 regs[REG_INDEX(R4)] = gregs.gpr[4]; 556 regs[REG_INDEX(R5)] = gregs.gpr[5]; 557 regs[REG_INDEX(R6)] = gregs.gpr[6]; 558 regs[REG_INDEX(R7)] = gregs.gpr[7]; 559 regs[REG_INDEX(R8)] = gregs.gpr[8]; 560 regs[REG_INDEX(R9)] = gregs.gpr[9]; 561 regs[REG_INDEX(R10)] = gregs.gpr[10]; 562 regs[REG_INDEX(R11)] = gregs.gpr[11]; 563 regs[REG_INDEX(R12)] = gregs.gpr[12]; 564 regs[REG_INDEX(R13)] = gregs.gpr[13]; 565 regs[REG_INDEX(R14)] = gregs.gpr[14]; 566 regs[REG_INDEX(R15)] = gregs.gpr[15]; 567 regs[REG_INDEX(R16)] = gregs.gpr[16]; 568 regs[REG_INDEX(R17)] = gregs.gpr[17]; 569 regs[REG_INDEX(R18)] = gregs.gpr[18]; 570 regs[REG_INDEX(R19)] = gregs.gpr[19]; 571 regs[REG_INDEX(R20)] = gregs.gpr[20]; 572 regs[REG_INDEX(R21)] = gregs.gpr[21]; 573 regs[REG_INDEX(R22)] = gregs.gpr[22]; 574 regs[REG_INDEX(R23)] = gregs.gpr[23]; 575 regs[REG_INDEX(R24)] = gregs.gpr[24]; 576 regs[REG_INDEX(R25)] = gregs.gpr[25]; 577 regs[REG_INDEX(R26)] = gregs.gpr[26]; 578 regs[REG_INDEX(R27)] = gregs.gpr[27]; 579 regs[REG_INDEX(R28)] = gregs.gpr[28]; 580 regs[REG_INDEX(R29)] = gregs.gpr[29]; 581 regs[REG_INDEX(R30)] = gregs.gpr[30]; 582 regs[REG_INDEX(R31)] = gregs.gpr[31]; 583 584 #endif 585 586 env->ReleaseLongArrayElements(array, regs, JNI_COMMIT); 587 return array; 588 } 589 #endif 590 591 /* 592 * Class: sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal 593 * Method: demangle 594 * Signature: (Ljava/lang/String;)Ljava/lang/String; 595 */ 596 extern "C" 597 JNIEXPORT jstring JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal_demangle 598 (JNIEnv *env, jobject this_obj, jstring jsym) { 599 int status; 600 jstring result = NULL; 601 602 const char *sym = env->GetStringUTFChars(jsym, NULL); 603 if (sym == NULL) { 604 THROW_NEW_DEBUGGER_EXCEPTION_("Error getting symbol string", NULL); 605 } 606 char *demangled = abi::__cxa_demangle(sym, NULL, 0, &status); 607 env->ReleaseStringUTFChars(jsym, sym); 608 if ((demangled != NULL) && (status == 0)) { 609 result = env->NewStringUTF(demangled); 610 free(demangled); 611 } else if (status == -2) { // not C++ ABI mangling rules - maybe C style 612 result = jsym; 613 } else { 614 THROW_NEW_DEBUGGER_EXCEPTION_("Could not demangle", NULL); 615 } 616 617 return result; 618 } 619 620 /* 621 * Class: sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal 622 * Method: findLibPtrByAddress0 623 * Signature: (J)J 624 */ 625 extern "C" 626 JNIEXPORT jlong JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal_findLibPtrByAddress0 627 (JNIEnv *env, jobject this_obj, jlong pc) { 628 struct ps_prochandle* ph = get_proc_handle(env, this_obj); 629 return reinterpret_cast<jlong>(find_lib_by_address(ph, pc)); 630 }