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