Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/jdk.hotspot.agent/macosx/native/libsaproc/MacosxDebuggerLocal.m
41149 views
1
/*
2
* Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved.
3
* Copyright (c) 2021, Azul Systems, Inc. All rights reserved.
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 <objc/objc-runtime.h>
27
#import <Foundation/Foundation.h>
28
29
#include <jni.h>
30
31
#import <mach/mach.h>
32
#import <mach/mach_types.h>
33
#import <sys/sysctl.h>
34
#import <stdio.h>
35
#import <string.h>
36
#import <stdarg.h>
37
#import <stdlib.h>
38
#import <strings.h>
39
#import <dlfcn.h>
40
#import <limits.h>
41
#import <errno.h>
42
#import <sys/types.h>
43
#import <sys/ptrace.h>
44
#include "libproc_impl.h"
45
46
#if defined(amd64)
47
#include "sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext.h"
48
#elif defined(aarch64)
49
#include "sun_jvm_hotspot_debugger_aarch64_AARCH64ThreadContext.h"
50
#else
51
#error UNSUPPORTED_ARCH
52
#endif
53
54
static jfieldID symbolicatorID = 0; // set in _init0
55
static jfieldID taskID = 0; // set in _init0
56
57
static jfieldID p_ps_prochandle_ID = 0;
58
static jfieldID loadObjectList_ID = 0;
59
static jmethodID listAdd_ID = 0;
60
61
static jmethodID createClosestSymbol_ID = 0;
62
static jmethodID createLoadObject_ID = 0;
63
static jmethodID getJavaThreadsInfo_ID = 0;
64
65
// indicator if thread id (lwpid_t) was set
66
static bool _threads_filled = false;
67
68
// mach_exc_server defined in the generated mach_excServer.c
69
extern boolean_t mach_exc_server(mach_msg_header_t *input_msg_hdr,
70
mach_msg_header_t *output_msg_hdr);
71
72
kern_return_t catch_mach_exception_raise(
73
mach_port_t exception_port, mach_port_t thread,
74
mach_port_t task, exception_type_t exception,
75
mach_exception_data_t code,
76
mach_msg_type_number_t code_cnt);
77
78
kern_return_t catch_mach_exception_raise_state(
79
mach_port_t exception_port, exception_type_t exception,
80
const mach_exception_data_t code, mach_msg_type_number_t code_cnt,
81
int *flavor, const thread_state_t old_state,
82
mach_msg_type_number_t old_state_cnt, thread_state_t new_state,
83
mach_msg_type_number_t *new_state_cnt);
84
85
kern_return_t catch_mach_exception_raise_state_identity(
86
mach_port_t exception_port, mach_port_t thread, mach_port_t task,
87
exception_type_t exception, mach_exception_data_t code,
88
mach_msg_type_number_t code_cnt, int *flavor, thread_state_t old_state,
89
mach_msg_type_number_t old_state_cnt, thread_state_t new_state,
90
mach_msg_type_number_t *new_state_cnt);
91
92
static struct exception_saved_state {
93
exception_mask_t saved_masks[EXC_TYPES_COUNT];
94
mach_port_t saved_ports[EXC_TYPES_COUNT];
95
exception_behavior_t saved_behaviors[EXC_TYPES_COUNT];
96
thread_state_flavor_t saved_flavors[EXC_TYPES_COUNT];
97
mach_msg_type_number_t saved_exception_types_count;
98
} exception_saved_state;
99
100
static mach_port_t tgt_exception_port;
101
102
// Mirrors __Reply__mach_exception_raise_t generated in mach_excServer.c
103
static struct rep_msg {
104
mach_msg_header_t header;
105
NDR_record_t ndr;
106
kern_return_t ret_code;
107
} rep_msg;
108
109
// Mirrors __Request__mach_exception_raise_t generated in mach_excServer.c
110
// with a large trailing pad to avoid MACH_MSG_RCV_TOO_LARGE
111
static struct exc_msg {
112
mach_msg_header_t header;
113
// start of the kernel processed data
114
mach_msg_body_t msgh_body;
115
mach_msg_port_descriptor_t thread;
116
mach_msg_port_descriptor_t task;
117
// end of the kernel processed data
118
NDR_record_t ndr;
119
exception_type_t exception;
120
mach_msg_type_number_t code_cnt;
121
mach_exception_data_t code; // an array of int64_t
122
char pad[512];
123
} exc_msg;
124
125
static void putSymbolicator(JNIEnv *env, jobject this_obj, id symbolicator) {
126
(*env)->SetLongField(env, this_obj, symbolicatorID, (jlong)(intptr_t)symbolicator);
127
}
128
129
static id getSymbolicator(JNIEnv *env, jobject this_obj) {
130
jlong ptr = (*env)->GetLongField(env, this_obj, symbolicatorID);
131
return (id)(intptr_t)ptr;
132
}
133
134
static void putTask(JNIEnv *env, jobject this_obj, task_t task) {
135
(*env)->SetLongField(env, this_obj, taskID, (jlong)task);
136
}
137
138
static task_t getTask(JNIEnv *env, jobject this_obj) {
139
jlong ptr = (*env)->GetLongField(env, this_obj, taskID);
140
return (task_t)ptr;
141
}
142
143
#define CHECK_EXCEPTION_(value) if ((*env)->ExceptionOccurred(env)) { return value; }
144
#define CHECK_EXCEPTION if ((*env)->ExceptionOccurred(env)) { return;}
145
#define THROW_NEW_DEBUGGER_EXCEPTION_(str, value) { throw_new_debugger_exception(env, str); return value; }
146
#define THROW_NEW_DEBUGGER_EXCEPTION(str) { throw_new_debugger_exception(env, str); return;}
147
#define CHECK_EXCEPTION_CLEAR if ((*env)->ExceptionOccurred(env)) { (*env)->ExceptionClear(env); }
148
#define CHECK_EXCEPTION_CLEAR_VOID if ((*env)->ExceptionOccurred(env)) { (*env)->ExceptionClear(env); return; }
149
#define CHECK_EXCEPTION_CLEAR_(value) if ((*env)->ExceptionOccurred(env)) { (*env)->ExceptionClear(env); return value; }
150
151
static void throw_new_debugger_exception(JNIEnv* env, const char* errMsg) {
152
jclass exceptionClass = (*env)->FindClass(env, "sun/jvm/hotspot/debugger/DebuggerException");
153
CHECK_EXCEPTION;
154
(*env)->ThrowNew(env, exceptionClass, errMsg);
155
}
156
157
static struct ps_prochandle* get_proc_handle(JNIEnv* env, jobject this_obj) {
158
jlong ptr = (*env)->GetLongField(env, this_obj, p_ps_prochandle_ID);
159
return (struct ps_prochandle*)(intptr_t)ptr;
160
}
161
162
#if defined(amd64)
163
#define hsdb_thread_state_t x86_thread_state64_t
164
#define hsdb_float_state_t x86_float_state64_t
165
#define HSDB_THREAD_STATE x86_THREAD_STATE64
166
#define HSDB_FLOAT_STATE x86_FLOAT_STATE64
167
#define HSDB_THREAD_STATE_COUNT x86_THREAD_STATE64_COUNT
168
#define HSDB_FLOAT_STATE_COUNT x86_FLOAT_STATE64_COUNT
169
#elif defined(aarch64)
170
#define hsdb_thread_state_t arm_thread_state64_t
171
#define hsdb_float_state_t arm_neon_state64_t
172
#define HSDB_THREAD_STATE ARM_THREAD_STATE64
173
#define HSDB_FLOAT_STATE ARM_NEON_STATE64
174
#define HSDB_THREAD_STATE_COUNT ARM_THREAD_STATE64_COUNT
175
#define HSDB_FLOAT_STATE_COUNT ARM_NEON_STATE64_COUNT
176
#else
177
#error UNSUPPORTED_ARCH
178
#endif
179
180
/*
181
* Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
182
* Method: init0
183
* Signature: ()V
184
*/
185
JNIEXPORT void JNICALL
186
Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_init0(JNIEnv *env, jclass cls) {
187
symbolicatorID = (*env)->GetFieldID(env, cls, "symbolicator", "J");
188
CHECK_EXCEPTION;
189
taskID = (*env)->GetFieldID(env, cls, "task", "J");
190
CHECK_EXCEPTION;
191
192
// for core file
193
p_ps_prochandle_ID = (*env)->GetFieldID(env, cls, "p_ps_prochandle", "J");
194
CHECK_EXCEPTION;
195
loadObjectList_ID = (*env)->GetFieldID(env, cls, "loadObjectList", "Ljava/util/List;");
196
CHECK_EXCEPTION;
197
198
// methods we use
199
createClosestSymbol_ID = (*env)->GetMethodID(env, cls, "createClosestSymbol",
200
"(Ljava/lang/String;J)Lsun/jvm/hotspot/debugger/cdbg/ClosestSymbol;");
201
CHECK_EXCEPTION;
202
createLoadObject_ID = (*env)->GetMethodID(env, cls, "createLoadObject",
203
"(Ljava/lang/String;JJ)Lsun/jvm/hotspot/debugger/cdbg/LoadObject;");
204
CHECK_EXCEPTION;
205
206
// java.util.List method we call
207
jclass listClass = (*env)->FindClass(env, "java/util/List");
208
CHECK_EXCEPTION;
209
listAdd_ID = (*env)->GetMethodID(env, listClass, "add", "(Ljava/lang/Object;)Z");
210
CHECK_EXCEPTION;
211
getJavaThreadsInfo_ID = (*env)->GetMethodID(env, cls, "getJavaThreadsInfo",
212
"()[J");
213
CHECK_EXCEPTION;
214
215
init_libproc(getenv("LIBSAPROC_DEBUG") != NULL);
216
}
217
218
JNIEXPORT jint JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_getAddressSize
219
(JNIEnv *env, jclass cls)
220
{
221
#ifdef _LP64
222
return 8;
223
#else
224
#error UNSUPPORTED_ARCH
225
#endif
226
}
227
228
/** called by Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_lookupByName0 */
229
jlong lookupByNameIncore(
230
JNIEnv *env, struct ps_prochandle *ph, jobject this_obj, jstring objectName, jstring symbolName)
231
{
232
const char *objectName_cstr, *symbolName_cstr;
233
jlong addr;
234
jboolean isCopy;
235
objectName_cstr = NULL;
236
if (objectName != NULL) {
237
objectName_cstr = (*env)->GetStringUTFChars(env, objectName, &isCopy);
238
CHECK_EXCEPTION_(0);
239
}
240
symbolName_cstr = (*env)->GetStringUTFChars(env, symbolName, &isCopy);
241
if ((*env)->ExceptionOccurred(env)) {
242
if (objectName_cstr != NULL) {
243
(*env)->ReleaseStringUTFChars(env, objectName, objectName_cstr);
244
}
245
return 0;
246
}
247
248
print_debug("look for %s \n", symbolName_cstr);
249
addr = (jlong) lookup_symbol(ph, objectName_cstr, symbolName_cstr);
250
251
if (objectName_cstr != NULL) {
252
(*env)->ReleaseStringUTFChars(env, objectName, objectName_cstr);
253
}
254
(*env)->ReleaseStringUTFChars(env, symbolName, symbolName_cstr);
255
return addr;
256
}
257
258
/* Create a pool and initiate a try block to catch any exception */
259
#define JNI_COCOA_ENTER(env) \
260
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; \
261
@try {
262
263
/* Don't allow NSExceptions to escape to Java.
264
* If there is a Java exception that has been thrown that should escape.
265
* And ensure we drain the auto-release pool.
266
*/
267
#define JNI_COCOA_EXIT(env) \
268
} \
269
@catch (NSException *e) { \
270
NSLog(@"%@", [e callStackSymbols]); \
271
} \
272
@finally { \
273
[pool drain]; \
274
};
275
276
static NSString* JavaStringToNSString(JNIEnv *env, jstring jstr) {
277
278
if (jstr == NULL) {
279
return NULL;
280
}
281
jsize len = (*env)->GetStringLength(env, jstr);
282
const jchar *chars = (*env)->GetStringChars(env, jstr, NULL);
283
if (chars == NULL) {
284
return NULL;
285
}
286
NSString *result = [NSString stringWithCharacters:(UniChar *)chars length:len];
287
(*env)->ReleaseStringChars(env, jstr, chars);
288
return result;
289
}
290
291
/*
292
* Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
293
* Method: lookupByName0
294
* Signature: (Ljava/lang/String;Ljava/lang/String;)J
295
*/
296
JNIEXPORT jlong JNICALL
297
Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_lookupByName0(
298
JNIEnv *env, jobject this_obj,
299
jstring objectName, jstring symbolName)
300
{
301
struct ps_prochandle* ph = get_proc_handle(env, this_obj);
302
if (ph != NULL && ph->core != NULL) {
303
return lookupByNameIncore(env, ph, this_obj, objectName, symbolName);
304
}
305
306
jlong address = 0;
307
308
JNI_COCOA_ENTER(env);
309
310
NSString *symbolNameString = JavaStringToNSString(env, symbolName);
311
312
print_debug("lookupInProcess called for %s\n", [symbolNameString UTF8String]);
313
314
id symbolicator = getSymbolicator(env, this_obj);
315
if (symbolicator != nil) {
316
uint64_t (*dynamicCall)(id, SEL, NSString *) = (uint64_t (*)(id, SEL, NSString *))&objc_msgSend;
317
address = (jlong) dynamicCall(symbolicator, @selector(addressForSymbol:), symbolNameString);
318
}
319
320
print_debug("address of symbol %s = %llx\n", [symbolNameString UTF8String], address);
321
JNI_COCOA_EXIT(env);
322
323
return address;
324
}
325
326
/*
327
* Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
328
* Method: lookupByAddress0
329
* Signature: (J)Lsun/jvm/hotspot/debugger/cdbg/ClosestSymbol;
330
*/
331
JNIEXPORT jobject JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_lookupByAddress0
332
(JNIEnv *env, jobject this_obj, jlong addr) {
333
uintptr_t offset;
334
const char* sym = NULL;
335
jstring sym_string;
336
337
struct ps_prochandle* ph = get_proc_handle(env, this_obj);
338
if (ph != NULL && ph->core != NULL) {
339
sym = symbol_for_pc(ph, (uintptr_t) addr, &offset);
340
if (sym == NULL) return 0;
341
sym_string = (*env)->NewStringUTF(env, sym);
342
CHECK_EXCEPTION_(0);
343
return (*env)->CallObjectMethod(env, this_obj, createClosestSymbol_ID,
344
sym_string, (jlong)offset);
345
}
346
return 0;
347
}
348
349
/** called from Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_readBytesFromProcess0 */
350
jbyteArray readBytesFromCore(
351
JNIEnv *env, struct ps_prochandle *ph, jobject this_obj, jlong addr, jlong numBytes)
352
{
353
jboolean isCopy;
354
jbyteArray array;
355
jbyte *bufPtr;
356
ps_err_e err;
357
358
array = (*env)->NewByteArray(env, numBytes);
359
CHECK_EXCEPTION_(0);
360
bufPtr = (*env)->GetByteArrayElements(env, array, &isCopy);
361
CHECK_EXCEPTION_(0);
362
363
err = ps_pread(ph, (psaddr_t) (uintptr_t)addr, bufPtr, numBytes);
364
(*env)->ReleaseByteArrayElements(env, array, bufPtr, 0);
365
return (err == PS_OK)? array : 0;
366
}
367
368
/*
369
* Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
370
* Method: readBytesFromProcess0
371
* Signature: (JJ)Lsun/jvm/hotspot/debugger/ReadResult;
372
*/
373
JNIEXPORT jbyteArray JNICALL
374
Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_readBytesFromProcess0(
375
JNIEnv *env, jobject this_obj,
376
jlong addr, jlong numBytes)
377
{
378
print_debug("readBytesFromProcess called. addr = %llx numBytes = %lld\n", addr, numBytes);
379
380
// must allocate storage instead of using former parameter buf
381
jbyteArray array;
382
383
struct ps_prochandle* ph = get_proc_handle(env, this_obj);
384
if (ph != NULL && ph->core != NULL) {
385
return readBytesFromCore(env, ph, this_obj, addr, numBytes);
386
}
387
388
array = (*env)->NewByteArray(env, numBytes);
389
CHECK_EXCEPTION_(0);
390
391
unsigned long alignedAddress;
392
unsigned long alignedLength = 0;
393
kern_return_t result;
394
vm_offset_t *pages;
395
int *mapped;
396
long pageCount;
397
uint byteCount;
398
int i;
399
unsigned long remaining;
400
401
alignedAddress = trunc_page(addr);
402
if (addr != alignedAddress) {
403
alignedLength += addr - alignedAddress;
404
}
405
alignedLength = round_page(numBytes);
406
pageCount = alignedLength/vm_page_size;
407
408
// Allocate storage for pages and flags.
409
pages = malloc(pageCount * sizeof(vm_offset_t));
410
if (pages == NULL) {
411
(*env)->DeleteLocalRef(env, array);
412
return NULL;
413
}
414
mapped = calloc(pageCount, sizeof(int));
415
if (mapped == NULL) {
416
(*env)->DeleteLocalRef(env, array);
417
free(pages);
418
return NULL;
419
}
420
421
task_t gTask = getTask(env, this_obj);
422
// Try to read each of the pages.
423
for (i = 0; i < pageCount; i++) {
424
result = vm_read(gTask, alignedAddress + i*vm_page_size, vm_page_size,
425
&pages[i], &byteCount);
426
mapped[i] = (result == KERN_SUCCESS);
427
// assume all failures are unmapped pages
428
}
429
430
print_debug("%ld pages\n", pageCount);
431
432
remaining = numBytes;
433
434
for (i = 0; i < pageCount; i++) {
435
unsigned long len = vm_page_size;
436
unsigned long start = 0;
437
438
if (i == 0) {
439
start = addr - alignedAddress;
440
len = vm_page_size - start;
441
}
442
443
if (i == (pageCount - 1)) {
444
len = remaining;
445
}
446
447
if (mapped[i]) {
448
print_debug("page %d mapped (len %ld start %ld)\n", i, len, start);
449
(*env)->SetByteArrayRegion(env, array, 0, len, ((jbyte *) pages[i] + start));
450
vm_deallocate(mach_task_self(), pages[i], vm_page_size);
451
}
452
453
remaining -= len;
454
}
455
456
free (pages);
457
free (mapped);
458
return array;
459
}
460
461
/** Only used for core file reading, set thread_id for threads which is got after core file parsed.
462
* Thread context is available in Mach-O core file but thread id is not. We can get thread id
463
* from Threads which store all java threads information when they are created. Here we can identify
464
* them as java threads by checking if a thread's rsp or rbp within a java thread's stack.
465
* Note Macosx uses unique_thread_id which is different from other platforms though printed ids
466
* are still pthread id. Function BsdDebuggerLocal.getJavaThreadsInfo returns an array of long
467
* integers to host all java threads' id, stack_start, stack_end as:
468
* [uid0, stack_start0, stack_end0, uid1, stack_start1, stack_end1, ...]
469
*
470
* The work cannot be done at init0 since Threads is not available yet(VM not initialized yet).
471
* This function should be called only once if succeeded
472
*/
473
bool fill_java_threads(JNIEnv* env, jobject this_obj, struct ps_prochandle* ph) {
474
int n = 0, i = 0, j;
475
struct reg regs;
476
477
jlongArray thrinfos = (*env)->CallObjectMethod(env, this_obj, getJavaThreadsInfo_ID);
478
CHECK_EXCEPTION_(false);
479
int len = (int)(*env)->GetArrayLength(env, thrinfos);
480
uint64_t* cinfos = (uint64_t *)(*env)->GetLongArrayElements(env, thrinfos, NULL);
481
CHECK_EXCEPTION_(false);
482
n = get_num_threads(ph);
483
print_debug("fill_java_threads called, num_of_thread = %d\n", n);
484
for (i = 0; i < n; i++) {
485
if (!get_nth_lwp_regs(ph, i, &regs)) {
486
print_debug("Could not get regs of thread %d, already set!\n", i);
487
(*env)->ReleaseLongArrayElements(env, thrinfos, (jlong*)cinfos, 0);
488
return false;
489
}
490
for (j = 0; j < len; j += 3) {
491
lwpid_t uid = cinfos[j];
492
uint64_t beg = cinfos[j + 1];
493
uint64_t end = cinfos[j + 2];
494
#if defined(amd64)
495
if ((regs.r_rsp < end && regs.r_rsp >= beg) ||
496
(regs.r_rbp < end && regs.r_rbp >= beg)) {
497
set_lwp_id(ph, i, uid);
498
break;
499
}
500
#elif defined(aarch64)
501
if ((regs.r_sp < end && regs.r_sp >= beg) ||
502
(regs.r_fp < end && regs.r_fp >= beg)) {
503
set_lwp_id(ph, i, uid);
504
break;
505
}
506
#else
507
#error UNSUPPORTED_ARCH
508
#endif
509
}
510
}
511
(*env)->ReleaseLongArrayElements(env, thrinfos, (jlong*)cinfos, 0);
512
CHECK_EXCEPTION_(false);
513
return true;
514
}
515
516
/* For core file only, called from
517
* Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_getThreadIntegerRegisterSet0
518
*/
519
jlongArray getThreadIntegerRegisterSetFromCore(JNIEnv *env, jobject this_obj, long lwp_id, struct ps_prochandle* ph) {
520
if (!_threads_filled) {
521
if (!fill_java_threads(env, this_obj, ph)) {
522
throw_new_debugger_exception(env, "Failed to fill in threads");
523
return 0;
524
} else {
525
_threads_filled = true;
526
}
527
}
528
529
struct reg gregs;
530
jboolean isCopy;
531
jlongArray array;
532
jlong *regs;
533
534
if (get_lwp_regs(ph, lwp_id, &gregs) != true) {
535
THROW_NEW_DEBUGGER_EXCEPTION_("get_thread_regs failed for a lwp", 0);
536
}
537
538
#undef NPRGREG
539
#undef REG_INDEX
540
#if defined(amd64)
541
#define NPRGREG sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_NPRGREG
542
#define REG_INDEX(reg) sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_##reg
543
#elif defined(aarch64)
544
#define NPRGREG sun_jvm_hotspot_debugger_aarch64_AARCH64ThreadContext_NPRGREG
545
#define REG_INDEX(reg) sun_jvm_hotspot_debugger_aarch64_AARCH64ThreadContext_##reg
546
#else
547
#error UNSUPPORTED_ARCH
548
#endif
549
550
array = (*env)->NewLongArray(env, NPRGREG);
551
CHECK_EXCEPTION_(0);
552
regs = (*env)->GetLongArrayElements(env, array, &isCopy);
553
554
#if defined(amd64)
555
556
regs[REG_INDEX(R15)] = gregs.r_r15;
557
regs[REG_INDEX(R14)] = gregs.r_r14;
558
regs[REG_INDEX(R13)] = gregs.r_r13;
559
regs[REG_INDEX(R12)] = gregs.r_r12;
560
regs[REG_INDEX(RBP)] = gregs.r_rbp;
561
regs[REG_INDEX(RBX)] = gregs.r_rbx;
562
regs[REG_INDEX(R11)] = gregs.r_r11;
563
regs[REG_INDEX(R10)] = gregs.r_r10;
564
regs[REG_INDEX(R9)] = gregs.r_r9;
565
regs[REG_INDEX(R8)] = gregs.r_r8;
566
regs[REG_INDEX(RAX)] = gregs.r_rax;
567
regs[REG_INDEX(RCX)] = gregs.r_rcx;
568
regs[REG_INDEX(RDX)] = gregs.r_rdx;
569
regs[REG_INDEX(RSI)] = gregs.r_rsi;
570
regs[REG_INDEX(RDI)] = gregs.r_rdi;
571
regs[REG_INDEX(RIP)] = gregs.r_rip;
572
regs[REG_INDEX(CS)] = gregs.r_cs;
573
regs[REG_INDEX(RSP)] = gregs.r_rsp;
574
regs[REG_INDEX(SS)] = gregs.r_ss;
575
regs[REG_INDEX(FSBASE)] = 0;
576
regs[REG_INDEX(GSBASE)] = 0;
577
regs[REG_INDEX(DS)] = gregs.r_ds;
578
regs[REG_INDEX(ES)] = gregs.r_es;
579
regs[REG_INDEX(FS)] = gregs.r_fs;
580
regs[REG_INDEX(GS)] = gregs.r_gs;
581
regs[REG_INDEX(TRAPNO)] = gregs.r_trapno;
582
regs[REG_INDEX(RFL)] = gregs.r_rflags;
583
584
#elif defined(aarch64)
585
586
regs[REG_INDEX(R0)] = gregs.r_r0;
587
regs[REG_INDEX(R1)] = gregs.r_r1;
588
regs[REG_INDEX(R2)] = gregs.r_r2;
589
regs[REG_INDEX(R3)] = gregs.r_r3;
590
regs[REG_INDEX(R4)] = gregs.r_r4;
591
regs[REG_INDEX(R5)] = gregs.r_r5;
592
regs[REG_INDEX(R6)] = gregs.r_r6;
593
regs[REG_INDEX(R7)] = gregs.r_r7;
594
regs[REG_INDEX(R8)] = gregs.r_r8;
595
regs[REG_INDEX(R9)] = gregs.r_r9;
596
regs[REG_INDEX(R10)] = gregs.r_r10;
597
regs[REG_INDEX(R11)] = gregs.r_r11;
598
regs[REG_INDEX(R12)] = gregs.r_r12;
599
regs[REG_INDEX(R13)] = gregs.r_r13;
600
regs[REG_INDEX(R14)] = gregs.r_r14;
601
regs[REG_INDEX(R15)] = gregs.r_r15;
602
regs[REG_INDEX(R16)] = gregs.r_r16;
603
regs[REG_INDEX(R17)] = gregs.r_r17;
604
regs[REG_INDEX(R18)] = gregs.r_r18;
605
regs[REG_INDEX(R19)] = gregs.r_r19;
606
regs[REG_INDEX(R20)] = gregs.r_r20;
607
regs[REG_INDEX(R21)] = gregs.r_r21;
608
regs[REG_INDEX(R22)] = gregs.r_r22;
609
regs[REG_INDEX(R23)] = gregs.r_r23;
610
regs[REG_INDEX(R24)] = gregs.r_r24;
611
regs[REG_INDEX(R25)] = gregs.r_r25;
612
regs[REG_INDEX(R26)] = gregs.r_r26;
613
regs[REG_INDEX(R27)] = gregs.r_r27;
614
regs[REG_INDEX(R28)] = gregs.r_r28;
615
regs[REG_INDEX(FP)] = gregs.r_fp;
616
regs[REG_INDEX(LR)] = gregs.r_lr;
617
regs[REG_INDEX(SP)] = gregs.r_sp;
618
regs[REG_INDEX(PC)] = gregs.r_pc;
619
620
#else
621
#error UNSUPPORTED_ARCH
622
#endif
623
624
(*env)->ReleaseLongArrayElements(env, array, regs, JNI_COMMIT);
625
return array;
626
}
627
628
/*
629
* Lookup the thread_t that corresponds to the given thread_id.
630
* The thread_id should be the result from calling thread_info() with THREAD_IDENTIFIER_INFO
631
* and reading the m_ident_info.thread_id returned.
632
* The returned thread_t is the mach send right to the kernel port for the corresponding thread.
633
*
634
* We cannot simply use the OSThread._thread_id field in the JVM. This is set to ::mach_thread_self()
635
* in the VM, but that thread port is not valid for a remote debugger to access the thread.
636
*/
637
thread_t
638
lookupThreadFromThreadId(task_t task, jlong thread_id) {
639
print_debug("lookupThreadFromThreadId thread_id=0x%llx\n", thread_id);
640
641
thread_array_t thread_list = NULL;
642
mach_msg_type_number_t thread_list_count = 0;
643
thread_t result_thread = 0;
644
int i;
645
646
// get the list of all the send rights
647
kern_return_t result = task_threads(task, &thread_list, &thread_list_count);
648
if (result != KERN_SUCCESS) {
649
print_debug("task_threads returned 0x%x\n", result);
650
return 0;
651
}
652
653
for(i = 0 ; i < thread_list_count; i++) {
654
thread_identifier_info_data_t m_ident_info;
655
mach_msg_type_number_t count = THREAD_IDENTIFIER_INFO_COUNT;
656
657
// get the THREAD_IDENTIFIER_INFO for the send right
658
result = thread_info(thread_list[i], THREAD_IDENTIFIER_INFO, (thread_info_t) &m_ident_info, &count);
659
if (result != KERN_SUCCESS) {
660
print_debug("thread_info returned 0x%x\n", result);
661
break;
662
}
663
664
// if this is the one we're looking for, return the send right
665
if (thread_id == m_ident_info.thread_id)
666
{
667
result_thread = thread_list[i];
668
break;
669
}
670
}
671
672
vm_size_t thread_list_size = (vm_size_t) (thread_list_count * sizeof (thread_t));
673
vm_deallocate(mach_task_self(), (vm_address_t) thread_list, thread_list_count);
674
675
return result_thread;
676
}
677
678
679
/*
680
* Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
681
* Method: getThreadIntegerRegisterSet0
682
* Signature: (J)[J
683
*/
684
JNIEXPORT jlongArray JNICALL
685
Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_getThreadIntegerRegisterSet0(
686
JNIEnv *env, jobject this_obj,
687
jlong thread_id)
688
{
689
print_debug("getThreadIntegerRegisterSet0 called\n");
690
691
struct ps_prochandle* ph = get_proc_handle(env, this_obj);
692
if (ph != NULL && ph->core != NULL) {
693
return getThreadIntegerRegisterSetFromCore(env, this_obj, thread_id, ph);
694
}
695
696
kern_return_t result;
697
thread_t tid;
698
mach_msg_type_number_t count = HSDB_THREAD_STATE_COUNT;
699
hsdb_thread_state_t state;
700
jlongArray registerArray;
701
jlong *primitiveArray;
702
task_t gTask = getTask(env, this_obj);
703
704
tid = lookupThreadFromThreadId(gTask, thread_id);
705
706
result = thread_get_state(tid, HSDB_THREAD_STATE, (thread_state_t)&state, &count);
707
708
if (result != KERN_SUCCESS) {
709
// This is not considered fatal. Unlike on Linux and Windows, we haven't seen a
710
// failure to get thread registers, but if it were to fail the response should
711
// be the same. By ignoring this error and returning NULL, stacking walking code
712
// will get null registers and fallback to using the "last java frame" if setup.
713
fprintf(stdout, "WARNING: getThreadIntegerRegisterSet0: thread_get_state failed (%d) for thread (%d)\n",
714
result, tid);
715
fflush(stdout);
716
return NULL;
717
}
718
719
#undef NPRGREG
720
#if defined(amd64)
721
#define NPRGREG sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_NPRGREG
722
#elif defined(aarch64)
723
#define NPRGREG sun_jvm_hotspot_debugger_aarch64_AARCH64ThreadContext_NPRGREG
724
#else
725
#error UNSUPPORTED_ARCH
726
#endif
727
728
// 64 bit
729
print_debug("Getting threads for a 64-bit process\n");
730
registerArray = (*env)->NewLongArray(env, NPRGREG);
731
CHECK_EXCEPTION_(0);
732
primitiveArray = (*env)->GetLongArrayElements(env, registerArray, NULL);
733
734
#if defined(amd64)
735
736
primitiveArray[REG_INDEX(R15)] = state.__r15;
737
primitiveArray[REG_INDEX(R14)] = state.__r14;
738
primitiveArray[REG_INDEX(R13)] = state.__r13;
739
primitiveArray[REG_INDEX(R12)] = state.__r12;
740
primitiveArray[REG_INDEX(R11)] = state.__r11;
741
primitiveArray[REG_INDEX(R10)] = state.__r10;
742
primitiveArray[REG_INDEX(R9)] = state.__r9;
743
primitiveArray[REG_INDEX(R8)] = state.__r8;
744
primitiveArray[REG_INDEX(RDI)] = state.__rdi;
745
primitiveArray[REG_INDEX(RSI)] = state.__rsi;
746
primitiveArray[REG_INDEX(RBP)] = state.__rbp;
747
primitiveArray[REG_INDEX(RBX)] = state.__rbx;
748
primitiveArray[REG_INDEX(RDX)] = state.__rdx;
749
primitiveArray[REG_INDEX(RCX)] = state.__rcx;
750
primitiveArray[REG_INDEX(RAX)] = state.__rax;
751
primitiveArray[REG_INDEX(TRAPNO)] = 0; // trapno, not used
752
primitiveArray[REG_INDEX(ERR)] = 0; // err, not used
753
primitiveArray[REG_INDEX(RIP)] = state.__rip;
754
primitiveArray[REG_INDEX(CS)] = state.__cs;
755
primitiveArray[REG_INDEX(RFL)] = state.__rflags;
756
primitiveArray[REG_INDEX(RSP)] = state.__rsp;
757
primitiveArray[REG_INDEX(SS)] = 0; // We don't have SS
758
primitiveArray[REG_INDEX(FS)] = state.__fs;
759
primitiveArray[REG_INDEX(GS)] = state.__gs;
760
primitiveArray[REG_INDEX(ES)] = 0;
761
primitiveArray[REG_INDEX(DS)] = 0;
762
primitiveArray[REG_INDEX(FSBASE)] = 0;
763
primitiveArray[REG_INDEX(GSBASE)] = 0;
764
765
#elif defined(aarch64)
766
767
primitiveArray[REG_INDEX(R0)] = state.__x[0];
768
primitiveArray[REG_INDEX(R1)] = state.__x[1];
769
primitiveArray[REG_INDEX(R2)] = state.__x[2];
770
primitiveArray[REG_INDEX(R3)] = state.__x[3];
771
primitiveArray[REG_INDEX(R4)] = state.__x[4];
772
primitiveArray[REG_INDEX(R5)] = state.__x[5];
773
primitiveArray[REG_INDEX(R6)] = state.__x[6];
774
primitiveArray[REG_INDEX(R7)] = state.__x[7];
775
primitiveArray[REG_INDEX(R8)] = state.__x[8];
776
primitiveArray[REG_INDEX(R9)] = state.__x[9];
777
primitiveArray[REG_INDEX(R10)] = state.__x[10];
778
primitiveArray[REG_INDEX(R11)] = state.__x[11];
779
primitiveArray[REG_INDEX(R12)] = state.__x[12];
780
primitiveArray[REG_INDEX(R13)] = state.__x[13];
781
primitiveArray[REG_INDEX(R14)] = state.__x[14];
782
primitiveArray[REG_INDEX(R15)] = state.__x[15];
783
primitiveArray[REG_INDEX(R16)] = state.__x[16];
784
primitiveArray[REG_INDEX(R17)] = state.__x[17];
785
primitiveArray[REG_INDEX(R18)] = state.__x[18];
786
primitiveArray[REG_INDEX(R19)] = state.__x[19];
787
primitiveArray[REG_INDEX(R20)] = state.__x[20];
788
primitiveArray[REG_INDEX(R21)] = state.__x[21];
789
primitiveArray[REG_INDEX(R22)] = state.__x[22];
790
primitiveArray[REG_INDEX(R23)] = state.__x[23];
791
primitiveArray[REG_INDEX(R24)] = state.__x[24];
792
primitiveArray[REG_INDEX(R25)] = state.__x[25];
793
primitiveArray[REG_INDEX(R26)] = state.__x[26];
794
primitiveArray[REG_INDEX(R27)] = state.__x[27];
795
primitiveArray[REG_INDEX(R28)] = state.__x[28];
796
primitiveArray[REG_INDEX(FP)] = state.__fp;
797
primitiveArray[REG_INDEX(LR)] = state.__lr;
798
primitiveArray[REG_INDEX(SP)] = state.__sp;
799
primitiveArray[REG_INDEX(PC)] = state.__pc;
800
801
#else
802
#error UNSUPPORTED_ARCH
803
#endif
804
805
print_debug("set registers\n");
806
807
(*env)->ReleaseLongArrayElements(env, registerArray, primitiveArray, 0);
808
return registerArray;
809
}
810
811
/*
812
* Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
813
* Method: translateTID0
814
* Signature: (I)I
815
*/
816
JNIEXPORT jint JNICALL
817
Java_sun_jvm_hotspot_debugger_macosx_MacOSXDebuggerLocal_translateTID0(
818
JNIEnv *env, jobject this_obj, jint tid)
819
{
820
print_debug("translateTID0 called on tid = 0x%x\n", (int)tid);
821
822
kern_return_t result;
823
thread_t foreign_tid, usable_tid;
824
mach_msg_type_name_t type;
825
826
foreign_tid = tid;
827
828
task_t gTask = getTask(env, this_obj);
829
result = mach_port_extract_right(gTask, foreign_tid,
830
MACH_MSG_TYPE_COPY_SEND,
831
&usable_tid, &type);
832
if (result != KERN_SUCCESS)
833
return -1;
834
835
print_debug("translateTID0: 0x%x -> 0x%x\n", foreign_tid, usable_tid);
836
837
return (jint) usable_tid;
838
}
839
840
// attach to a process/thread specified by "pid"
841
static bool ptrace_attach(pid_t pid) {
842
errno = 0;
843
ptrace(PT_ATTACHEXC, pid, 0, 0);
844
845
if (errno != 0) {
846
print_error("ptrace_attach: ptrace(PT_ATTACHEXC,...) failed: %s", strerror(errno));
847
return false;
848
}
849
return true;
850
}
851
852
kern_return_t catch_mach_exception_raise(
853
mach_port_t exception_port, mach_port_t thread_port, mach_port_t task_port,
854
exception_type_t exception_type, mach_exception_data_t codes,
855
mach_msg_type_number_t num_codes) {
856
857
print_debug("catch_mach_exception_raise: Exception port = %d thread_port = %d "
858
"task port %d exc type = %d num_codes %d\n",
859
exception_port, thread_port, task_port, exception_type, num_codes);
860
861
// This message should denote a Unix soft signal, with
862
// 1. the exception type = EXC_SOFTWARE
863
// 2. codes[0] (which is the code) = EXC_SOFT_SIGNAL
864
// 3. codes[1] (which is the sub-code) = SIGSTOP
865
if (!(exception_type == EXC_SOFTWARE &&
866
codes[0] == EXC_SOFT_SIGNAL &&
867
codes[num_codes -1] == SIGSTOP)) {
868
print_error("catch_mach_exception_raise: Message doesn't denote a Unix "
869
"soft signal. exception_type = %d, codes[0] = %d, "
870
"codes[num_codes -1] = %d, num_codes = %d\n",
871
exception_type, codes[0], codes[num_codes - 1], num_codes);
872
return MACH_RCV_INVALID_TYPE;
873
}
874
return KERN_SUCCESS;
875
}
876
877
kern_return_t catch_mach_exception_raise_state(
878
mach_port_t exception_port, exception_type_t exception, const mach_exception_data_t code,
879
mach_msg_type_number_t code_cnt, int *flavor, const thread_state_t old_state,
880
mach_msg_type_number_t old_state_cnt, thread_state_t new_state,
881
mach_msg_type_number_t *new_state_cnt) {
882
return MACH_RCV_INVALID_TYPE;
883
}
884
885
886
kern_return_t catch_mach_exception_raise_state_identity(
887
mach_port_t exception_port, mach_port_t thread, mach_port_t task,
888
exception_type_t exception, mach_exception_data_t code,
889
mach_msg_type_number_t code_cnt, int *flavor,
890
thread_state_t old_state, mach_msg_type_number_t old_state_cnt,
891
thread_state_t new_state, mach_msg_type_number_t *new_state_cnt) {
892
return MACH_RCV_INVALID_TYPE;
893
}
894
895
// wait to receive an exception message
896
static bool wait_for_exception() {
897
kern_return_t result;
898
899
result = mach_msg(&exc_msg.header,
900
MACH_RCV_MSG,
901
0,
902
sizeof(exc_msg),
903
tgt_exception_port,
904
MACH_MSG_TIMEOUT_NONE,
905
MACH_PORT_NULL);
906
907
if (result != MACH_MSG_SUCCESS) {
908
print_error("attach: wait_for_exception: mach_msg() failed: '%s' (%d)\n",
909
mach_error_string(result), result);
910
return false;
911
}
912
913
if (mach_exc_server(&exc_msg.header, &rep_msg.header) == false ||
914
rep_msg.ret_code != KERN_SUCCESS) {
915
print_error("attach: wait_for_exception: mach_exc_server failure\n");
916
if (rep_msg.ret_code != KERN_SUCCESS) {
917
print_error("catch_mach_exception_raise() failed '%s' (%d)\n",
918
mach_error_string(rep_msg.ret_code), rep_msg.ret_code);
919
}
920
return false;
921
}
922
923
print_debug("reply msg from mach_exc_server: (msg->{bits = %#x, size = %u, "
924
"remote_port = %#x, local_port = %#x, reserved = 0x%x, id = 0x%x},)",
925
rep_msg.header.msgh_bits, rep_msg.header.msgh_size,
926
rep_msg.header.msgh_remote_port, rep_msg.header.msgh_local_port,
927
rep_msg.header.msgh_reserved, rep_msg.header.msgh_id);
928
929
return true;
930
}
931
932
/*
933
* Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
934
* Method: attach0
935
* Signature: (I)V
936
*/
937
JNIEXPORT void JNICALL
938
Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_attach0__I(
939
JNIEnv *env, jobject this_obj, jint jpid)
940
{
941
print_debug("attach0 called for jpid=%d\n", (int)jpid);
942
943
JNI_COCOA_ENTER(env);
944
945
kern_return_t result;
946
task_t gTask = 0;
947
948
result = task_for_pid(mach_task_self(), jpid, &gTask);
949
if (result != KERN_SUCCESS) {
950
print_error("attach: task_for_pid(%d) failed: '%s' (%d)\n", (int)jpid, mach_error_string(result), result);
951
THROW_NEW_DEBUGGER_EXCEPTION(
952
"Can't attach to the process. Could be caused by an incorrect pid or lack of privileges.");
953
}
954
putTask(env, this_obj, gTask);
955
956
// Allocate an exception port.
957
result = mach_port_allocate(mach_task_self(),
958
MACH_PORT_RIGHT_RECEIVE,
959
&tgt_exception_port);
960
if (result != KERN_SUCCESS) {
961
print_error("attach: mach_port_allocate() for tgt_exception_port failed: '%s' (%d)\n",
962
mach_error_string(result), result);
963
THROW_NEW_DEBUGGER_EXCEPTION(
964
"Can't attach to the process. Couldn't allocate an exception port.");
965
}
966
967
// Enable the new exception port to send messages.
968
result = mach_port_insert_right (mach_task_self(),
969
tgt_exception_port,
970
tgt_exception_port,
971
MACH_MSG_TYPE_MAKE_SEND);
972
if (result != KERN_SUCCESS) {
973
print_error("attach: mach_port_insert_right() failed for port 0x%x: '%s' (%d)\n",
974
tgt_exception_port, mach_error_string(result), result);
975
THROW_NEW_DEBUGGER_EXCEPTION(
976
"Can't attach to the process. Couldn't add send privileges to the exception port.");
977
}
978
979
// Save the existing original exception ports registered with the target
980
// process (for later restoration while detaching from the process).
981
result = task_get_exception_ports(gTask,
982
EXC_MASK_ALL,
983
exception_saved_state.saved_masks,
984
&exception_saved_state.saved_exception_types_count,
985
exception_saved_state.saved_ports,
986
exception_saved_state.saved_behaviors,
987
exception_saved_state.saved_flavors);
988
989
if (result != KERN_SUCCESS) {
990
print_error("attach: task_get_exception_ports() failed: '%s' (%d)\n",
991
mach_error_string(result), result);
992
THROW_NEW_DEBUGGER_EXCEPTION(
993
"Can't attach to the process. Could not get the target exception ports.");
994
}
995
996
// register the exception port to be used for all future exceptions with the
997
// target process.
998
result = task_set_exception_ports(gTask,
999
EXC_MASK_ALL,
1000
tgt_exception_port,
1001
EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES,
1002
THREAD_STATE_NONE);
1003
1004
if (result != KERN_SUCCESS) {
1005
print_error("attach: task_set_exception_ports() failed -- port 0x%x: '%s' (%d)\n",
1006
tgt_exception_port, mach_error_string(result), result);
1007
mach_port_deallocate(mach_task_self(), gTask);
1008
mach_port_deallocate(mach_task_self(), tgt_exception_port);
1009
THROW_NEW_DEBUGGER_EXCEPTION(
1010
"Can't attach to the process. Could not register the exception port "
1011
"with the target process.");
1012
}
1013
1014
// use ptrace to stop the process
1015
// on os x, ptrace only needs to be called on the process, not the individual threads
1016
if (ptrace_attach(jpid) != true) {
1017
print_error("attach: ptrace failure in attaching to %d\n", (int)jpid);
1018
mach_port_deallocate(mach_task_self(), gTask);
1019
mach_port_deallocate(mach_task_self(), tgt_exception_port);
1020
THROW_NEW_DEBUGGER_EXCEPTION("Can't ptrace attach to the process");
1021
}
1022
1023
if (wait_for_exception() != true) {
1024
mach_port_deallocate(mach_task_self(), gTask);
1025
mach_port_deallocate(mach_task_self(), tgt_exception_port);
1026
THROW_NEW_DEBUGGER_EXCEPTION(
1027
"Can't attach to the process. Issues with reception of the exception message.");
1028
}
1029
1030
// suspend all the threads in the task
1031
result = task_suspend(gTask);
1032
if (result != KERN_SUCCESS) {
1033
print_error("attach: task_suspend() failed: '%s' (%d)\n",
1034
mach_error_string(result), result);
1035
mach_port_deallocate(mach_task_self(), gTask);
1036
mach_port_deallocate(mach_task_self(), tgt_exception_port);
1037
THROW_NEW_DEBUGGER_EXCEPTION("Can't attach. Unable to suspend all the threads in the task.");
1038
}
1039
1040
id symbolicator = nil;
1041
id jrsSymbolicator = objc_lookUpClass("JRSSymbolicator");
1042
if (jrsSymbolicator != nil) {
1043
id (*dynamicCall)(id, SEL, pid_t) = (id (*)(id, SEL, pid_t))&objc_msgSend;
1044
symbolicator = dynamicCall(jrsSymbolicator, @selector(symbolicatorForPid:), (pid_t)jpid);
1045
}
1046
if (symbolicator != nil) {
1047
CFRetain(symbolicator); // pin symbolicator while in java heap
1048
}
1049
1050
putSymbolicator(env, this_obj, symbolicator);
1051
if (symbolicator == nil) {
1052
mach_port_deallocate(mach_task_self(), gTask);
1053
mach_port_deallocate(mach_task_self(), tgt_exception_port);
1054
THROW_NEW_DEBUGGER_EXCEPTION("Can't attach symbolicator to the process");
1055
}
1056
1057
JNI_COCOA_EXIT(env);
1058
}
1059
1060
/** For core file,
1061
called from Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_attach0__Ljava_lang_String_2Ljava_lang_String_2 */
1062
static void fillLoadObjects(JNIEnv* env, jobject this_obj, struct ps_prochandle* ph) {
1063
int n = 0, i = 0;
1064
jobject loadObjectList;
1065
1066
loadObjectList = (*env)->GetObjectField(env, this_obj, loadObjectList_ID);
1067
CHECK_EXCEPTION;
1068
1069
// add load objects
1070
n = get_num_libs(ph);
1071
for (i = 0; i < n; i++) {
1072
uintptr_t base, memsz;
1073
const char* name;
1074
jobject loadObject;
1075
jstring nameString;
1076
1077
get_lib_addr_range(ph, i, &base, &memsz);
1078
name = get_lib_name(ph, i);
1079
nameString = (*env)->NewStringUTF(env, name);
1080
CHECK_EXCEPTION;
1081
loadObject = (*env)->CallObjectMethod(env, this_obj, createLoadObject_ID,
1082
nameString, (jlong)memsz, (jlong)base);
1083
CHECK_EXCEPTION;
1084
(*env)->CallBooleanMethod(env, loadObjectList, listAdd_ID, loadObject);
1085
CHECK_EXCEPTION;
1086
(*env)->DeleteLocalRef(env, nameString);
1087
(*env)->DeleteLocalRef(env, loadObject);
1088
}
1089
}
1090
1091
/*
1092
* Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
1093
* Method: attach0
1094
* Signature: (Ljava/lang/String;Ljava/lang/String;)V
1095
*/
1096
JNIEXPORT void JNICALL
1097
Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_attach0__Ljava_lang_String_2Ljava_lang_String_2(
1098
JNIEnv *env, jobject this_obj, jstring execName, jstring coreName)
1099
{
1100
const char *execName_cstr;
1101
const char *coreName_cstr;
1102
jboolean isCopy;
1103
struct ps_prochandle* ph;
1104
1105
execName_cstr = (*env)->GetStringUTFChars(env, execName, &isCopy);
1106
CHECK_EXCEPTION;
1107
coreName_cstr = (*env)->GetStringUTFChars(env, coreName, &isCopy);
1108
if ((*env)->ExceptionOccurred(env)) {
1109
(*env)->ReleaseStringUTFChars(env, execName, execName_cstr);
1110
return;
1111
}
1112
1113
print_debug("attach: %s %s\n", execName_cstr, coreName_cstr);
1114
1115
if ( (ph = Pgrab_core(execName_cstr, coreName_cstr)) == NULL) {
1116
(*env)->ReleaseStringUTFChars(env, execName, execName_cstr);
1117
(*env)->ReleaseStringUTFChars(env, coreName, coreName_cstr);
1118
THROW_NEW_DEBUGGER_EXCEPTION("Can't attach to the core file");
1119
}
1120
(*env)->SetLongField(env, this_obj, p_ps_prochandle_ID, (jlong)(intptr_t)ph);
1121
(*env)->ReleaseStringUTFChars(env, execName, execName_cstr);
1122
(*env)->ReleaseStringUTFChars(env, coreName, coreName_cstr);
1123
fillLoadObjects(env, this_obj, ph);
1124
}
1125
1126
static void detach_cleanup(task_t gTask, JNIEnv *env, jobject this_obj, bool throw_exception) {
1127
mach_port_deallocate(mach_task_self(), tgt_exception_port);
1128
mach_port_deallocate(mach_task_self(), gTask);
1129
1130
id symbolicator = getSymbolicator(env, this_obj);
1131
if (symbolicator != nil) {
1132
CFRelease(symbolicator);
1133
}
1134
if (throw_exception) {
1135
THROW_NEW_DEBUGGER_EXCEPTION("Cannot detach.");
1136
}
1137
}
1138
1139
/*
1140
* Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
1141
* Method: detach0
1142
* Signature: ()V
1143
*/
1144
JNIEXPORT void JNICALL
1145
Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_detach0(
1146
JNIEnv *env, jobject this_obj)
1147
{
1148
print_debug("detach0 called\n");
1149
struct ps_prochandle* ph = get_proc_handle(env, this_obj);
1150
if (ph != NULL && ph->core != NULL) {
1151
Prelease(ph);
1152
return;
1153
}
1154
1155
JNI_COCOA_ENTER(env);
1156
1157
task_t gTask = getTask(env, this_obj);
1158
kern_return_t k_res = 0;
1159
1160
// Restore the pre-saved original exception ports registered with the target process
1161
for (uint32_t i = 0; i < exception_saved_state.saved_exception_types_count; ++i) {
1162
k_res = task_set_exception_ports(gTask,
1163
exception_saved_state.saved_masks[i],
1164
exception_saved_state.saved_ports[i],
1165
exception_saved_state.saved_behaviors[i],
1166
exception_saved_state.saved_flavors[i]);
1167
if (k_res != KERN_SUCCESS) {
1168
print_error("detach: task_set_exception_ports failed with %d while "
1169
"restoring the target exception ports.\n", k_res);
1170
detach_cleanup(gTask, env, this_obj, true);
1171
}
1172
}
1173
1174
// detach from the ptraced process causing it to resume execution
1175
int pid;
1176
k_res = pid_for_task(gTask, &pid);
1177
if (k_res != KERN_SUCCESS) {
1178
print_error("detach: pid_for_task(%d) failed (%d)\n", pid, k_res);
1179
detach_cleanup(gTask, env, this_obj, true);
1180
}
1181
else {
1182
errno = 0;
1183
ptrace(PT_DETACH, pid, (caddr_t)1, 0);
1184
if (errno != 0) {
1185
print_error("detach: ptrace(PT_DETACH,...) failed: %s", strerror(errno));
1186
detach_cleanup(gTask, env, this_obj, true);
1187
}
1188
}
1189
1190
// reply to the previous exception message
1191
k_res = mach_msg(&rep_msg.header,
1192
MACH_SEND_MSG| MACH_SEND_INTERRUPT,
1193
rep_msg.header.msgh_size,
1194
0,
1195
MACH_PORT_NULL,
1196
MACH_MSG_TIMEOUT_NONE,
1197
MACH_PORT_NULL);
1198
if (k_res != MACH_MSG_SUCCESS) {
1199
print_error("detach: mach_msg() for replying to pending exceptions failed: '%s' (%d)\n",
1200
mach_error_string(k_res), k_res);
1201
detach_cleanup(gTask, env, this_obj, true);
1202
}
1203
1204
detach_cleanup(gTask, env, this_obj, false);
1205
1206
JNI_COCOA_EXIT(env);
1207
}
1208
1209