1 /*
2  * Copyright (c) 2002, 2017, 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 <stdlib.h>
26 #if defined(__FreeBSD__) || defined(__DragonFly__)
27 #include <machine/sysarch.h>
28 #endif
29 #include <cxxabi.h>
30 #include <jni.h>
31 #include "libproc.h"
32 
33 #if defined(x86_64) && !defined(amd64)
34 #define amd64 1
35 #endif
36 
37 #ifdef i386
38 #include "sun_jvm_hotspot_debugger_x86_X86ThreadContext.h"
39 #endif
40 
41 #ifdef amd64
42 #include "sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext.h"
43 #endif
44 
45 #if defined(sparc) || defined(sparcv9)
46 #include "sun_jvm_hotspot_debugger_sparc_SPARCThreadContext.h"
47 #endif
48 
49 #if defined(ppc64) || defined(ppc64le)
50 #include "sun_jvm_hotspot_debugger_ppc64_PPC64ThreadContext.h"
51 #endif
52 
53 #ifdef aarch64
54 #include "sun_jvm_hotspot_debugger_aarch64_AARCH64ThreadContext.h"
55 #endif
56 
57 static jfieldID p_ps_prochandle_ID = 0;
58 static jfieldID threadList_ID = 0;
59 static jfieldID loadObjectList_ID = 0;
60 
61 static jmethodID createClosestSymbol_ID = 0;
62 static jmethodID createLoadObject_ID = 0;
63 static jmethodID getThreadForThreadId_ID = 0;
64 static jmethodID listAdd_ID = 0;
65 
66 #define CHECK_EXCEPTION_(value) if (env->ExceptionOccurred()) { return value; }
67 #define CHECK_EXCEPTION if (env->ExceptionOccurred()) { return;}
68 #define THROW_NEW_DEBUGGER_EXCEPTION_(str, value) { throw_new_debugger_exception(env, str); return value; }
69 #define THROW_NEW_DEBUGGER_EXCEPTION(str) { throw_new_debugger_exception(env, str); return;}
70 
throw_new_debugger_exception(JNIEnv * env,const char * errMsg)71 void throw_new_debugger_exception(JNIEnv* env, const char* errMsg) {
72   jclass clazz;
73   clazz = env->FindClass("sun/jvm/hotspot/debugger/DebuggerException");
74   CHECK_EXCEPTION;
75   env->ThrowNew(clazz, errMsg);
76 }
77 
get_proc_handle(JNIEnv * env,jobject this_obj)78 struct ps_prochandle* get_proc_handle(JNIEnv* env, jobject this_obj) {
79   jlong ptr = env->GetLongField(this_obj, p_ps_prochandle_ID);
80   return (struct ps_prochandle*)(intptr_t)ptr;
81 }
82 
83 /*
84  * Class:     sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
85  * Method:    init0
86  * Signature: ()V
87  */
88 extern "C"
Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_init0(JNIEnv * env,jclass cls)89 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_init0
90   (JNIEnv *env, jclass cls) {
91   jclass listClass;
92 
93   if (init_libproc(getenv("LIBSAPROC_DEBUG") != NULL) != true) {
94      THROW_NEW_DEBUGGER_EXCEPTION("can't initialize libproc");
95   }
96 
97   // fields we use
98   p_ps_prochandle_ID = env->GetFieldID(cls, "p_ps_prochandle", "J");
99   CHECK_EXCEPTION;
100   threadList_ID = env->GetFieldID(cls, "threadList", "Ljava/util/List;");
101   CHECK_EXCEPTION;
102   loadObjectList_ID = env->GetFieldID(cls, "loadObjectList", "Ljava/util/List;");
103   CHECK_EXCEPTION;
104 
105   // methods we use
106   createClosestSymbol_ID = env->GetMethodID(cls, "createClosestSymbol",
107                     "(Ljava/lang/String;J)Lsun/jvm/hotspot/debugger/cdbg/ClosestSymbol;");
108   CHECK_EXCEPTION;
109   createLoadObject_ID = env->GetMethodID(cls, "createLoadObject",
110                     "(Ljava/lang/String;JJ)Lsun/jvm/hotspot/debugger/cdbg/LoadObject;");
111   CHECK_EXCEPTION;
112   getThreadForThreadId_ID = env->GetMethodID(cls, "getThreadForThreadId",
113                                                      "(J)Lsun/jvm/hotspot/debugger/ThreadProxy;");
114   CHECK_EXCEPTION;
115   // java.util.List method we call
116   listClass = env->FindClass("java/util/List");
117   CHECK_EXCEPTION;
118   listAdd_ID = env->GetMethodID(listClass, "add", "(Ljava/lang/Object;)Z");
119   CHECK_EXCEPTION;
120 }
121 
122 extern "C"
Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_getAddressSize(JNIEnv * env,jclass cls)123 JNIEXPORT jint JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_getAddressSize
124   (JNIEnv *env, jclass cls)
125 {
126 #ifdef _LP64
127  return 8;
128 #else
129  return 4;
130 #endif
131 
132 }
133 
134 
fillThreadsAndLoadObjects(JNIEnv * env,jobject this_obj,struct ps_prochandle * ph)135 static void fillThreadsAndLoadObjects(JNIEnv* env, jobject this_obj, struct ps_prochandle* ph) {
136   int n = 0, i = 0;
137 
138   // add threads
139   n = get_num_threads(ph);
140   for (i = 0; i < n; i++) {
141     jobject thread;
142     jobject threadList;
143     lwpid_t lwpid;
144 
145     lwpid = get_lwp_id(ph, i);
146     thread = env->CallObjectMethod(this_obj, getThreadForThreadId_ID, (jlong)lwpid);
147     CHECK_EXCEPTION;
148     threadList = env->GetObjectField(this_obj, threadList_ID);
149     CHECK_EXCEPTION;
150     env->CallBooleanMethod(threadList, listAdd_ID, thread);
151     CHECK_EXCEPTION;
152   }
153 
154   // add load objects
155   n = get_num_libs(ph);
156   for (i = 0; i < n; i++) {
157      uintptr_t base;
158      const char* name;
159      jobject loadObject;
160      jobject loadObjectList;
161      jstring str;
162 
163      base = get_lib_base(ph, i);
164      name = get_lib_name(ph, i);
165 
166      str = env->NewStringUTF(name);
167      CHECK_EXCEPTION;
168      loadObject = env->CallObjectMethod(this_obj, createLoadObject_ID, str, (jlong)0, (jlong)base);
169      CHECK_EXCEPTION;
170      loadObjectList = env->GetObjectField(this_obj, loadObjectList_ID);
171      CHECK_EXCEPTION;
172      env->CallBooleanMethod(loadObjectList, listAdd_ID, loadObject);
173      CHECK_EXCEPTION;
174   }
175 }
176 
177 /*
178  * Class:     sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
179  * Method:    attach0
180  * Signature: (I)V
181  */
182 extern "C"
Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_attach0__I(JNIEnv * env,jobject this_obj,jint jpid)183 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_attach0__I
184   (JNIEnv *env, jobject this_obj, jint jpid) {
185 
186   char err_buf[200];
187   struct ps_prochandle* ph;
188   if ( (ph = Pgrab(jpid, err_buf, sizeof(err_buf))) == NULL) {
189     char msg[230];
190     snprintf(msg, sizeof(msg), "Can't attach to the process: %s", err_buf);
191     THROW_NEW_DEBUGGER_EXCEPTION(msg);
192   }
193   env->SetLongField(this_obj, p_ps_prochandle_ID, (jlong)(intptr_t)ph);
194   fillThreadsAndLoadObjects(env, this_obj, ph);
195 }
196 
197 /*
198  * Class:     sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
199  * Method:    attach0
200  * Signature: (Ljava/lang/String;Ljava/lang/String;)V
201  */
202 extern "C"
Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_attach0__Ljava_lang_String_2Ljava_lang_String_2(JNIEnv * env,jobject this_obj,jstring execName,jstring coreName)203 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_attach0__Ljava_lang_String_2Ljava_lang_String_2
204   (JNIEnv *env, jobject this_obj, jstring execName, jstring coreName) {
205   const char *execName_cstr;
206   const char *coreName_cstr;
207   jboolean isCopy;
208   struct ps_prochandle* ph;
209 
210   execName_cstr = env->GetStringUTFChars(execName, &isCopy);
211   CHECK_EXCEPTION;
212   coreName_cstr = env->GetStringUTFChars(coreName, &isCopy);
213   CHECK_EXCEPTION;
214 
215   if ( (ph = Pgrab_core(execName_cstr, coreName_cstr)) == NULL) {
216     env->ReleaseStringUTFChars(execName, execName_cstr);
217     env->ReleaseStringUTFChars(coreName, coreName_cstr);
218     THROW_NEW_DEBUGGER_EXCEPTION("Can't attach to the core file");
219   }
220   env->SetLongField(this_obj, p_ps_prochandle_ID, (jlong)(intptr_t)ph);
221   env->ReleaseStringUTFChars(execName, execName_cstr);
222   env->ReleaseStringUTFChars(coreName, coreName_cstr);
223   fillThreadsAndLoadObjects(env, this_obj, ph);
224 }
225 
226 /*
227  * Class:     sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
228  * Method:    detach0
229  * Signature: ()V
230  */
231 extern "C"
Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_detach0(JNIEnv * env,jobject this_obj)232 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_detach0
233   (JNIEnv *env, jobject this_obj) {
234   struct ps_prochandle* ph = get_proc_handle(env, this_obj);
235   if (ph != NULL) {
236      Prelease(ph);
237   }
238 }
239 
240 /*
241  * Class:     sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
242  * Method:    lookupByName0
243  * Signature: (Ljava/lang/String;Ljava/lang/String;)J
244  */
245 extern "C"
Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_lookupByName0(JNIEnv * env,jobject this_obj,jstring objectName,jstring symbolName)246 JNIEXPORT jlong JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_lookupByName0
247   (JNIEnv *env, jobject this_obj, jstring objectName, jstring symbolName) {
248   const char *objectName_cstr, *symbolName_cstr;
249   jlong addr;
250   jboolean isCopy;
251   struct ps_prochandle* ph = get_proc_handle(env, this_obj);
252 
253   objectName_cstr = NULL;
254   if (objectName != NULL) {
255     objectName_cstr = env->GetStringUTFChars(objectName, &isCopy);
256     CHECK_EXCEPTION_(0);
257   }
258   symbolName_cstr = env->GetStringUTFChars(symbolName, &isCopy);
259   CHECK_EXCEPTION_(0);
260 
261   addr = (jlong) lookup_symbol(ph, objectName_cstr, symbolName_cstr);
262 
263   if (objectName_cstr != NULL) {
264     env->ReleaseStringUTFChars(objectName, objectName_cstr);
265   }
266   env->ReleaseStringUTFChars(symbolName, symbolName_cstr);
267   return addr;
268 }
269 
270 /*
271  * Class:     sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
272  * Method:    lookupByAddress0
273  * Signature: (J)Lsun/jvm/hotspot/debugger/cdbg/ClosestSymbol;
274  */
275 extern "C"
Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_lookupByAddress0(JNIEnv * env,jobject this_obj,jlong addr)276 JNIEXPORT jobject JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_lookupByAddress0
277   (JNIEnv *env, jobject this_obj, jlong addr) {
278   uintptr_t offset;
279   jobject obj;
280   jstring str;
281   const char* sym = NULL;
282 
283   struct ps_prochandle* ph = get_proc_handle(env, this_obj);
284   sym = symbol_for_pc(ph, (uintptr_t) addr, &offset);
285   if (sym == NULL) return 0;
286   str = env->NewStringUTF(sym);
287   CHECK_EXCEPTION_(NULL);
288   obj = env->CallObjectMethod(this_obj, createClosestSymbol_ID, str, (jlong)offset);
289   CHECK_EXCEPTION_(NULL);
290   return obj;
291 }
292 
293 /*
294  * Class:     sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
295  * Method:    readBytesFromProcess0
296  * Signature: (JJ)Lsun/jvm/hotspot/debugger/ReadResult;
297  */
298 extern "C"
Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_readBytesFromProcess0(JNIEnv * env,jobject this_obj,jlong addr,jlong numBytes)299 JNIEXPORT jbyteArray JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_readBytesFromProcess0
300   (JNIEnv *env, jobject this_obj, jlong addr, jlong numBytes) {
301 
302   jboolean isCopy;
303   jbyteArray array;
304   jbyte *bufPtr;
305   ps_err_e err;
306 
307   array = env->NewByteArray(numBytes);
308   CHECK_EXCEPTION_(0);
309   bufPtr = env->GetByteArrayElements(array, &isCopy);
310   CHECK_EXCEPTION_(0);
311 
312 #ifdef __DragonFly__
313   err = PS_ERR; /* XXX unsupported */
314 #else
315   err = ps_pread(get_proc_handle(env, this_obj), (psaddr_t) (uintptr_t)addr, bufPtr, numBytes);
316 #endif
317   env->ReleaseByteArrayElements(array, bufPtr, 0);
318   return (err == PS_OK)? array : 0;
319 }
320 
321 extern "C"
Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_getThreadIntegerRegisterSet0(JNIEnv * env,jobject this_obj,jint lwp_id)322 JNIEXPORT jlongArray JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_getThreadIntegerRegisterSet0
323   (JNIEnv *env, jobject this_obj, jint lwp_id) {
324 
325   struct reg gregs;
326   jboolean isCopy;
327   jlongArray array;
328   jlong *regs;
329 
330   struct ps_prochandle* ph = get_proc_handle(env, this_obj);
331   if (get_lwp_regs(ph, lwp_id, &gregs) != true) {
332      THROW_NEW_DEBUGGER_EXCEPTION_("get_thread_regs failed for a lwp", 0);
333   }
334 
335 #undef NPRGREG
336 #ifdef i386
337 #define NPRGREG sun_jvm_hotspot_debugger_x86_X86ThreadContext_NPRGREG
338 #endif
339 #ifdef amd64
340 #define NPRGREG sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_NPRGREG
341 #endif
342 #if defined(sparc) || defined(sparcv9)
343 #define NPRGREG sun_jvm_hotspot_debugger_sparc_SPARCThreadContext_NPRGREG
344 #endif
345 #if defined(ppc64) || defined(ppc64le)
346 #define NPRGREG sun_jvm_hotspot_debugger_ppc64_PPC64ThreadContext_NPRGREG
347 #endif
348 #ifdef aarch64
349 #define NPRGREG sun_jvm_hotspot_debugger_aarch64_AARCH64ThreadContext_NPRGREG
350 #endif
351 
352   array = env->NewLongArray(NPRGREG);
353   CHECK_EXCEPTION_(0);
354   regs = env->GetLongArrayElements(array, &isCopy);
355 
356 #undef REG_INDEX
357 
358 #ifdef i386
359 #define REG_INDEX(reg) sun_jvm_hotspot_debugger_x86_X86ThreadContext_##reg
360 
361   regs[REG_INDEX(GS)]  = (uintptr_t) gregs.r_gs;
362   regs[REG_INDEX(FS)]  = (uintptr_t) gregs.r_fs;
363   regs[REG_INDEX(ES)]  = (uintptr_t) gregs.r_es;
364   regs[REG_INDEX(DS)]  = (uintptr_t) gregs.r_ds;
365   regs[REG_INDEX(EDI)] = (uintptr_t) gregs.r_edi;
366   regs[REG_INDEX(ESI)] = (uintptr_t) gregs.r_esi;
367   regs[REG_INDEX(FP)] = (uintptr_t) gregs.r_ebp;
368   regs[REG_INDEX(SP)] = (uintptr_t) gregs.r_isp;
369   regs[REG_INDEX(EBX)] = (uintptr_t) gregs.r_ebx;
370   regs[REG_INDEX(EDX)] = (uintptr_t) gregs.r_edx;
371   regs[REG_INDEX(ECX)] = (uintptr_t) gregs.r_ecx;
372   regs[REG_INDEX(EAX)] = (uintptr_t) gregs.r_eax;
373   regs[REG_INDEX(PC)] = (uintptr_t) gregs.r_eip;
374   regs[REG_INDEX(CS)]  = (uintptr_t) gregs.r_cs;
375   regs[REG_INDEX(SS)]  = (uintptr_t) gregs.r_ss;
376 
377 #endif /* i386 */
378 
379 #ifdef amd64
380 #define REG_INDEX(reg) sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_##reg
381 
382   regs[REG_INDEX(R15)] = gregs.r_r15;
383   regs[REG_INDEX(R14)] = gregs.r_r14;
384   regs[REG_INDEX(R13)] = gregs.r_r13;
385   regs[REG_INDEX(R12)] = gregs.r_r12;
386   regs[REG_INDEX(RBP)] = gregs.r_rbp;
387   regs[REG_INDEX(RBX)] = gregs.r_rbx;
388   regs[REG_INDEX(R11)] = gregs.r_r11;
389   regs[REG_INDEX(R10)] = gregs.r_r10;
390   regs[REG_INDEX(R9)] = gregs.r_r9;
391   regs[REG_INDEX(R8)] = gregs.r_r8;
392   regs[REG_INDEX(RAX)] = gregs.r_rax;
393   regs[REG_INDEX(RCX)] = gregs.r_rcx;
394   regs[REG_INDEX(RDX)] = gregs.r_rdx;
395   regs[REG_INDEX(RSI)] = gregs.r_rsi;
396   regs[REG_INDEX(RDI)] = gregs.r_rdi;
397   regs[REG_INDEX(RIP)] = gregs.r_rip;
398   regs[REG_INDEX(CS)] = gregs.r_cs;
399   regs[REG_INDEX(RSP)] = gregs.r_rsp;
400   regs[REG_INDEX(SS)] = gregs.r_ss;
401 #if defined(__FreeBSD__) || defined(__DragonFly__)
402   void **fs_base = NULL, **gs_base = NULL;
403   amd64_get_fsbase(fs_base);
404   amd64_get_gsbase(gs_base);
405 
406   regs[REG_INDEX(FSBASE)] = (long) *fs_base;
407   regs[REG_INDEX(GSBASE)] = (long) *gs_base;
408 #ifndef __DragonFly__
409   regs[REG_INDEX(DS)] = gregs.r_ds;
410   regs[REG_INDEX(ES)] = gregs.r_es;
411   regs[REG_INDEX(FS)] = gregs.r_fs;
412   regs[REG_INDEX(GS)] = gregs.r_gs;
413 #endif
414 #endif /* __FreeBSD__ */
415 
416 #endif /* amd64 */
417 
418 #if defined(sparc) || defined(sparcv9)
419 
420 #define REG_INDEX(reg) sun_jvm_hotspot_debugger_sparc_SPARCThreadContext_##reg
421 
422 #ifdef _LP64
423   regs[REG_INDEX(R_PSR)] = gregs.tstate;
424   regs[REG_INDEX(R_PC)]  = gregs.tpc;
425   regs[REG_INDEX(R_nPC)] = gregs.tnpc;
426   regs[REG_INDEX(R_Y)]   = gregs.y;
427 #else
428   regs[REG_INDEX(R_PSR)] = gregs.psr;
429   regs[REG_INDEX(R_PC)]  = gregs.pc;
430   regs[REG_INDEX(R_nPC)] = gregs.npc;
431   regs[REG_INDEX(R_Y)]   = gregs.y;
432 #endif
433   regs[REG_INDEX(R_G0)]  =            0 ;
434   regs[REG_INDEX(R_G1)]  = gregs.u_regs[0];
435   regs[REG_INDEX(R_G2)]  = gregs.u_regs[1];
436   regs[REG_INDEX(R_G3)]  = gregs.u_regs[2];
437   regs[REG_INDEX(R_G4)]  = gregs.u_regs[3];
438   regs[REG_INDEX(R_G5)]  = gregs.u_regs[4];
439   regs[REG_INDEX(R_G6)]  = gregs.u_regs[5];
440   regs[REG_INDEX(R_G7)]  = gregs.u_regs[6];
441   regs[REG_INDEX(R_O0)]  = gregs.u_regs[7];
442   regs[REG_INDEX(R_O1)]  = gregs.u_regs[8];
443   regs[REG_INDEX(R_O2)]  = gregs.u_regs[ 9];
444   regs[REG_INDEX(R_O3)]  = gregs.u_regs[10];
445   regs[REG_INDEX(R_O4)]  = gregs.u_regs[11];
446   regs[REG_INDEX(R_O5)]  = gregs.u_regs[12];
447   regs[REG_INDEX(R_O6)]  = gregs.u_regs[13];
448   regs[REG_INDEX(R_O7)]  = gregs.u_regs[14];
449 #endif /* sparc */
450 #if defined(ppc64) || defined(ppc64le)
451 #define REG_INDEX(reg) sun_jvm_hotspot_debugger_ppc64_PPC64ThreadContext_##reg
452 
453   regs[REG_INDEX(LR)] = gregs.lr;
454   regs[REG_INDEX(PC)] = gregs.pc;
455   regs[REG_INDEX(R0)]  = gregs.fixreg[0];
456   regs[REG_INDEX(R1)]  = gregs.fixreg[1];
457   regs[REG_INDEX(R2)]  = gregs.fixreg[2];
458   regs[REG_INDEX(R3)]  = gregs.fixreg[3];
459   regs[REG_INDEX(R4)]  = gregs.fixreg[4];
460   regs[REG_INDEX(R5)]  = gregs.fixreg[5];
461   regs[REG_INDEX(R6)]  = gregs.fixreg[6];
462   regs[REG_INDEX(R7)]  = gregs.fixreg[7];
463   regs[REG_INDEX(R8)]  = gregs.fixreg[8];
464   regs[REG_INDEX(R9)]  = gregs.fixreg[9];
465   regs[REG_INDEX(R10)] = gregs.fixreg[10];
466   regs[REG_INDEX(R11)] = gregs.fixreg[11];
467   regs[REG_INDEX(R12)] = gregs.fixreg[12];
468   regs[REG_INDEX(R13)] = gregs.fixreg[13];
469   regs[REG_INDEX(R14)] = gregs.fixreg[14];
470   regs[REG_INDEX(R15)] = gregs.fixreg[15];
471   regs[REG_INDEX(R16)] = gregs.fixreg[16];
472   regs[REG_INDEX(R17)] = gregs.fixreg[17];
473   regs[REG_INDEX(R18)] = gregs.fixreg[18];
474   regs[REG_INDEX(R19)] = gregs.fixreg[19];
475   regs[REG_INDEX(R20)] = gregs.fixreg[20];
476   regs[REG_INDEX(R21)] = gregs.fixreg[21];
477   regs[REG_INDEX(R22)] = gregs.fixreg[22];
478   regs[REG_INDEX(R23)] = gregs.fixreg[23];
479   regs[REG_INDEX(R24)] = gregs.fixreg[24];
480   regs[REG_INDEX(R25)] = gregs.fixreg[25];
481   regs[REG_INDEX(R26)] = gregs.fixreg[26];
482   regs[REG_INDEX(R27)] = gregs.fixreg[27];
483   regs[REG_INDEX(R28)] = gregs.fixreg[28];
484   regs[REG_INDEX(R29)] = gregs.fixreg[29];
485   regs[REG_INDEX(R30)] = gregs.fixreg[30];
486   regs[REG_INDEX(R31)] = gregs.fixreg[31];
487 
488 #endif /* ppc64 */
489 #if defined(aarch64)
490 
491 #define REG_INDEX(reg) sun_jvm_hotspot_debugger_aarch64_AARCH64ThreadContext_##reg
492 
493   {
494     int i;
495     for (i = 0; i < 31; i++)
496       regs[i] = gregs.x[i];
497     regs[REG_INDEX(SP)] = gregs.sp;
498     regs[REG_INDEX(PC)] = gregs.elr;
499   }
500 #endif /* aarch64 */
501 
502 
503   env->ReleaseLongArrayElements(array, regs, JNI_COMMIT);
504   return array;
505 }
506 
507 /*
508  * Class:     sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
509  * Method:    demangle
510  * Signature: (Ljava/lang/String;)Ljava/lang/String;
511  */
512 extern "C"
Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_demangle(JNIEnv * env,jobject this_obj,jstring jsym)513 JNIEXPORT jstring JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_demangle
514   (JNIEnv *env, jobject this_obj, jstring jsym) {
515   int status;
516   jstring result = NULL;
517 
518   const char *sym = env->GetStringUTFChars(jsym, JNI_FALSE);
519   char *demangled = abi::__cxa_demangle(sym, NULL, 0, &status);
520   env->ReleaseStringUTFChars(jsym, sym);
521   if ((demangled != NULL) && (status == 0)) {
522     result = env->NewStringUTF(demangled);
523     free(demangled);
524   } else if (status == -2) { // not C++ ABI mangling rules - maybe C style
525     result = jsym;
526   } else {
527     THROW_NEW_DEBUGGER_EXCEPTION_("Could not demangle", NULL);
528   }
529 
530   return result;
531 }
532