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