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