Mercurial > hg > truffle
comparison agent/src/os/bsd/MacosxDebuggerLocal.m @ 4006:436b4a3231bf
7098194: integrate macosx-port changes
Summary: Integrate bsd-port/hotspot and macosx-port/hotspot changes as of 2011.09.29.
Reviewed-by: kvn, dholmes, never, phh
Contributed-by: Christos Zoulas <christos@zoulas.com>, Greg Lewis <glewis@eyesbeyond.com>, Kurt Miller <kurt@intricatesoftware.com>, Alexander Strange <astrange@apple.com>, Mike Swingler <swingler@apple.com>, Roger Hoover <rhoover@apple.com>, Victor Hernandez <vhernandez@apple.com>, Pratik Solanki <psolanki@apple.com>
author | dcubed |
---|---|
date | Thu, 13 Oct 2011 09:35:42 -0700 |
parents | |
children | 5a98bf7d847b |
comparison
equal
deleted
inserted
replaced
4005:2ef3386478e6 | 4006:436b4a3231bf |
---|---|
1 /* | |
2 * Copyright (c) 2002, 2007, 2011, 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 <objc/objc-runtime.h> | |
26 #import <Foundation/Foundation.h> | |
27 #import <JavaNativeFoundation/JavaNativeFoundation.h> | |
28 | |
29 #include <JavaVM/jni.h> | |
30 | |
31 #import <mach/mach.h> | |
32 #import <mach/mach_types.h> | |
33 #import <sys/sysctl.h> | |
34 #import <stdlib.h> | |
35 | |
36 jboolean debug = JNI_FALSE; | |
37 | |
38 static jfieldID symbolicatorID = 0; // set in _init0 | |
39 static jfieldID taskID = 0; // set in _init0 | |
40 | |
41 static void putSymbolicator(JNIEnv *env, jobject this_obj, id symbolicator) { | |
42 (*env)->SetLongField(env, this_obj, symbolicatorID, (jlong)(intptr_t)symbolicator); | |
43 } | |
44 | |
45 static id getSymbolicator(JNIEnv *env, jobject this_obj) { | |
46 jlong ptr = (*env)->GetLongField(env, this_obj, symbolicatorID); | |
47 return (id)(intptr_t)ptr; | |
48 } | |
49 | |
50 static void putTask(JNIEnv *env, jobject this_obj, task_t task) { | |
51 (*env)->SetLongField(env, this_obj, taskID, (jlong)task); | |
52 } | |
53 | |
54 static task_t getTask(JNIEnv *env, jobject this_obj) { | |
55 jlong ptr = (*env)->GetLongField(env, this_obj, taskID); | |
56 return (task_t)ptr; | |
57 } | |
58 | |
59 #define CHECK_EXCEPTION_(value) if ((*env)->ExceptionOccurred(env)) { return value; } | |
60 #define CHECK_EXCEPTION if ((*env)->ExceptionOccurred(env)) { return;} | |
61 #define THROW_NEW_DEBUGGER_EXCEPTION_(str, value) { throw_new_debugger_exception(env, str); return value; } | |
62 #define THROW_NEW_DEBUGGER_EXCEPTION(str) { throw_new_debugger_exception(env, str); return;} | |
63 | |
64 static void throw_new_debugger_exception(JNIEnv* env, const char* errMsg) { | |
65 (*env)->ThrowNew(env, (*env)->FindClass(env, "sun/jvm/hotspot/debugger/DebuggerException"), errMsg); | |
66 } | |
67 | |
68 #if defined(__i386__) | |
69 #define hsdb_thread_state_t x86_thread_state32_t | |
70 #define hsdb_float_state_t x86_float_state32_t | |
71 #define HSDB_THREAD_STATE x86_THREAD_STATE32 | |
72 #define HSDB_FLOAT_STATE x86_FLOAT_STATE32 | |
73 #define HSDB_THREAD_STATE_COUNT x86_THREAD_STATE32_COUNT | |
74 #define HSDB_FLOAT_STATE_COUNT x86_FLOAT_STATE32_COUNT | |
75 #elif defined(__x86_64__) | |
76 #define hsdb_thread_state_t x86_thread_state64_t | |
77 #define hsdb_float_state_t x86_float_state64_t | |
78 #define HSDB_THREAD_STATE x86_THREAD_STATE64 | |
79 #define HSDB_FLOAT_STATE x86_FLOAT_STATE64 | |
80 #define HSDB_THREAD_STATE_COUNT x86_THREAD_STATE64_COUNT | |
81 #define HSDB_FLOAT_STATE_COUNT x86_FLOAT_STATE64_COUNT | |
82 #else | |
83 #error "Unsupported architecture" | |
84 #endif | |
85 | |
86 /* | |
87 * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal | |
88 * Method: init0 | |
89 * Signature: ()V | |
90 */ | |
91 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_init0(JNIEnv *env, jclass cls) { | |
92 symbolicatorID = (*env)->GetFieldID(env, cls, "symbolicator", "J"); | |
93 taskID = (*env)->GetFieldID(env, cls, "task", "J"); | |
94 CHECK_EXCEPTION; | |
95 } | |
96 | |
97 /* | |
98 * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal | |
99 * Method: lookupByName0 | |
100 * Signature: (Ljava/lang/String;Ljava/lang/String;)J | |
101 */ | |
102 JNIEXPORT jlong JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_lookupByName0(JNIEnv *env, jobject this_obj, jstring objectName, jstring symbolName) { | |
103 jlong address = 0; | |
104 | |
105 JNF_COCOA_ENTER(env); | |
106 NSString *symbolNameString = JNFJavaToNSString(env, symbolName); | |
107 | |
108 if (debug) { | |
109 printf("lookupInProcess called for %s\n", [symbolNameString UTF8String]); | |
110 } | |
111 | |
112 id symbolicator = getSymbolicator(env, this_obj); | |
113 if (symbolicator != nil) { | |
114 uint64_t (*dynamicCall)(id, SEL, NSString *) = (uint64_t (*)(id, SEL, NSString *))&objc_msgSend; | |
115 address = (jlong) dynamicCall(symbolicator, @selector(addressForSymbol:), symbolNameString); | |
116 } | |
117 | |
118 if (debug) { | |
119 printf("address of symbol %s = %llx\n", [symbolNameString UTF8String], address); | |
120 } | |
121 JNF_COCOA_EXIT(env); | |
122 | |
123 return address; | |
124 } | |
125 | |
126 /* | |
127 * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal | |
128 * Method: readBytesFromProcess0 | |
129 * Signature: (JJ)Lsun/jvm/hotspot/debugger/ReadResult; | |
130 */ | |
131 JNIEXPORT jbyteArray JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_readBytesFromProcess0(JNIEnv *env, jobject this_obj, jlong addr, jlong numBytes) { | |
132 if (debug) printf("readBytesFromProcess called. addr = %llx numBytes = %lld\n", addr, numBytes); | |
133 | |
134 // must allocate storage instead of using former parameter buf | |
135 jboolean isCopy; | |
136 jbyteArray array; | |
137 jbyte *bufPtr; | |
138 | |
139 array = (*env)->NewByteArray(env, numBytes); | |
140 CHECK_EXCEPTION_(0); | |
141 | |
142 unsigned long alignedAddress; | |
143 unsigned long alignedLength; | |
144 kern_return_t result; | |
145 vm_offset_t *pages; | |
146 int *mapped; | |
147 long pageCount; | |
148 uint byteCount; | |
149 int i; | |
150 unsigned long remaining; | |
151 | |
152 alignedAddress = trunc_page(addr); | |
153 if (addr != alignedAddress) { | |
154 alignedLength += addr - alignedAddress; | |
155 } | |
156 alignedLength = round_page(numBytes); | |
157 pageCount = alignedLength/vm_page_size; | |
158 | |
159 // Allocate storage for pages and flags. | |
160 pages = malloc(pageCount * sizeof(vm_offset_t)); | |
161 mapped = calloc(pageCount, sizeof(int)); | |
162 | |
163 task_t gTask = getTask(env, this_obj); | |
164 // Try to read each of the pages. | |
165 for (i = 0; i < pageCount; i++) { | |
166 result = vm_read(gTask, alignedAddress + i*vm_page_size, vm_page_size, | |
167 &pages[i], &byteCount); | |
168 mapped[i] = (result == KERN_SUCCESS); | |
169 // assume all failures are unmapped pages | |
170 } | |
171 | |
172 if (debug) fprintf(stderr, "%ld pages\n", pageCount); | |
173 | |
174 remaining = numBytes; | |
175 | |
176 for (i = 0; i < pageCount; i++) { | |
177 unsigned long len = vm_page_size; | |
178 unsigned long start = 0; | |
179 | |
180 if (i == 0) { | |
181 start = addr - alignedAddress; | |
182 len = vm_page_size - start; | |
183 } | |
184 | |
185 if (i == (pageCount - 1)) { | |
186 len = remaining; | |
187 } | |
188 | |
189 if (mapped[i]) { | |
190 if (debug) fprintf(stderr, "page %d mapped (len %ld start %ld)\n", i, len, start); | |
191 (*env)->SetByteArrayRegion(env, array, 0, len, ((jbyte *) pages[i] + start)); | |
192 vm_deallocate(mach_task_self(), pages[i], vm_page_size); | |
193 } | |
194 | |
195 remaining -= len; | |
196 } | |
197 | |
198 free (pages); | |
199 free (mapped); | |
200 return array; | |
201 } | |
202 | |
203 /* | |
204 * Class: sun_jvm_hotspot_debugger_macosx_MacOSXDebuggerLocal | |
205 * Method: getThreadIntegerRegisterSet0 | |
206 * Signature: (I)[J | |
207 */ | |
208 JNIEXPORT jlongArray JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_getThreadIntegerRegisterSet0(JNIEnv *env, jobject this_obj, jint lwp_id) { | |
209 if (debug) | |
210 printf("getThreadRegisterSet0 called\n"); | |
211 | |
212 kern_return_t result; | |
213 thread_t tid; | |
214 mach_msg_type_number_t count = HSDB_THREAD_STATE_COUNT; | |
215 hsdb_thread_state_t state; | |
216 unsigned int *r; | |
217 int i; | |
218 jlongArray registerArray; | |
219 jlong *primitiveArray; | |
220 | |
221 tid = lwp_id; | |
222 | |
223 result = thread_get_state(tid, HSDB_THREAD_STATE, (thread_state_t)&state, &count); | |
224 | |
225 if (result != KERN_SUCCESS) { | |
226 if (debug) | |
227 printf("getregs: thread_get_state(%d) failed (%d)\n", tid, result); | |
228 return NULL; | |
229 } | |
230 | |
231 // 40 32-bit registers on ppc, 16 on x86. | |
232 // Output order is the same as the order in the ppc_thread_state/i386_thread_state struct. | |
233 #if defined(__i386__) | |
234 r = (unsigned int *)&state; | |
235 registerArray = (*env)->NewLongArray(env, 8); | |
236 primitiveArray = (*env)->GetLongArrayElements(env, registerArray, NULL); | |
237 primitiveArray[0] = r[0]; // eax | |
238 primitiveArray[1] = r[2]; // ecx | |
239 primitiveArray[2] = r[3]; // edx | |
240 primitiveArray[3] = r[1]; // ebx | |
241 primitiveArray[4] = r[7]; // esp | |
242 primitiveArray[5] = r[6]; // ebp | |
243 primitiveArray[6] = r[5]; // esi | |
244 primitiveArray[7] = r[4]; // edi | |
245 (*env)->ReleaseLongArrayElements(env, registerArray, primitiveArray, 0); | |
246 #elif defined(__x86_64__) | |
247 /* From AMD64ThreadContext.java | |
248 public static final int R15 = 0; | |
249 public static final int R14 = 1; | |
250 public static final int R13 = 2; | |
251 public static final int R12 = 3; | |
252 public static final int R11 = 4; | |
253 public static final int R10 = 5; | |
254 public static final int R9 = 6; | |
255 public static final int R8 = 7; | |
256 public static final int RDI = 8; | |
257 public static final int RSI = 9; | |
258 public static final int RBP = 10; | |
259 public static final int RBX = 11; | |
260 public static final int RDX = 12; | |
261 public static final int RCX = 13; | |
262 public static final int RAX = 14; | |
263 public static final int TRAPNO = 15; | |
264 public static final int ERR = 16; | |
265 public static final int RIP = 17; | |
266 public static final int CS = 18; | |
267 public static final int RFL = 19; | |
268 public static final int RSP = 20; | |
269 public static final int SS = 21; | |
270 public static final int FS = 22; | |
271 public static final int GS = 23; | |
272 public static final int ES = 24; | |
273 public static final int DS = 25; | |
274 public static final int FSBASE = 26; | |
275 public static final int GSBASE = 27; | |
276 */ | |
277 // 64 bit | |
278 if (debug) printf("Getting threads for a 64-bit process\n"); | |
279 registerArray = (*env)->NewLongArray(env, 28); | |
280 primitiveArray = (*env)->GetLongArrayElements(env, registerArray, NULL); | |
281 | |
282 primitiveArray[0] = state.__r15; | |
283 primitiveArray[1] = state.__r14; | |
284 primitiveArray[2] = state.__r13; | |
285 primitiveArray[3] = state.__r12; | |
286 primitiveArray[4] = state.__r11; | |
287 primitiveArray[5] = state.__r10; | |
288 primitiveArray[6] = state.__r9; | |
289 primitiveArray[7] = state.__r8; | |
290 primitiveArray[8] = state.__rdi; | |
291 primitiveArray[9] = state.__rsi; | |
292 primitiveArray[10] = state.__rbp; | |
293 primitiveArray[11] = state.__rbx; | |
294 primitiveArray[12] = state.__rdx; | |
295 primitiveArray[13] = state.__rcx; | |
296 primitiveArray[14] = state.__rax; | |
297 primitiveArray[15] = 0; // trapno ? | |
298 primitiveArray[16] = 0; // err ? | |
299 primitiveArray[17] = state.__rip; | |
300 primitiveArray[18] = state.__cs; | |
301 primitiveArray[19] = state.__rflags; | |
302 primitiveArray[20] = state.__rsp; | |
303 primitiveArray[21] = 0; // We don't have SS | |
304 primitiveArray[22] = state.__fs; | |
305 primitiveArray[23] = state.__gs; | |
306 primitiveArray[24] = 0; | |
307 primitiveArray[25] = 0; | |
308 primitiveArray[26] = 0; | |
309 primitiveArray[27] = 0; | |
310 | |
311 if (debug) printf("set registers\n"); | |
312 | |
313 (*env)->ReleaseLongArrayElements(env, registerArray, primitiveArray, 0); | |
314 #else | |
315 #error Unsupported architecture | |
316 #endif | |
317 | |
318 return registerArray; | |
319 } | |
320 | |
321 /* | |
322 * Class: sun_jvm_hotspot_debugger_macosx_MacOSXDebuggerLocal | |
323 * Method: translateTID0 | |
324 * Signature: (I)I | |
325 */ | |
326 JNIEXPORT jint JNICALL | |
327 Java_sun_jvm_hotspot_debugger_macosx_MacOSXDebuggerLocal_translateTID0(JNIEnv *env, jobject this_obj, jint tid) { | |
328 if (debug) | |
329 printf("translateTID0 called on tid = 0x%x\n", (int)tid); | |
330 | |
331 kern_return_t result; | |
332 thread_t foreign_tid, usable_tid; | |
333 mach_msg_type_name_t type; | |
334 | |
335 foreign_tid = tid; | |
336 | |
337 task_t gTask = getTask(env, this_obj); | |
338 result = mach_port_extract_right(gTask, foreign_tid, | |
339 MACH_MSG_TYPE_COPY_SEND, | |
340 &usable_tid, &type); | |
341 if (result != KERN_SUCCESS) | |
342 return -1; | |
343 | |
344 if (debug) | |
345 printf("translateTID0: 0x%x -> 0x%x\n", foreign_tid, usable_tid); | |
346 | |
347 return (jint) usable_tid; | |
348 } | |
349 | |
350 /* | |
351 * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal | |
352 * Method: attach0 | |
353 * Signature: (I)V | |
354 */ | |
355 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_attach0__I(JNIEnv *env, jobject this_obj, jint jpid) { | |
356 JNF_COCOA_ENTER(env); | |
357 if (getenv("JAVA_SAPROC_DEBUG") != NULL) | |
358 debug = JNI_TRUE; | |
359 else | |
360 debug = JNI_FALSE; | |
361 if (debug) printf("attach0 called for jpid=%d\n", (int)jpid); | |
362 | |
363 kern_return_t result; | |
364 task_t gTask = 0; | |
365 result = task_for_pid(mach_task_self(), jpid, &gTask); | |
366 if (result != KERN_SUCCESS) { | |
367 fprintf(stderr, "attach: task_for_pid(%d) failed (%d)\n", (int)jpid, result); | |
368 THROW_NEW_DEBUGGER_EXCEPTION("Can't attach to the process"); | |
369 } | |
370 putTask(env, this_obj, gTask); | |
371 | |
372 id symbolicator = nil; | |
373 id jrsSymbolicator = objc_lookUpClass("JRSSymbolicator"); | |
374 if (jrsSymbolicator != nil) { | |
375 id (*dynamicCall)(id, SEL, pid_t) = (id (*)(id, SEL, pid_t))&objc_msgSend; | |
376 symbolicator = dynamicCall(jrsSymbolicator, @selector(symbolicatorForPid:), (pid_t)jpid); | |
377 } | |
378 if (symbolicator != nil) { | |
379 CFRetain(symbolicator); // pin symbolicator while in java heap | |
380 } | |
381 | |
382 putSymbolicator(env, this_obj, symbolicator); | |
383 if (symbolicator == nil) { | |
384 THROW_NEW_DEBUGGER_EXCEPTION("Can't attach symbolicator to the process"); | |
385 } | |
386 | |
387 JNF_COCOA_EXIT(env); | |
388 } | |
389 | |
390 /* | |
391 * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal | |
392 * Method: detach0 | |
393 * Signature: ()V | |
394 */ | |
395 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_detach0(JNIEnv *env, jobject this_obj) { | |
396 JNF_COCOA_ENTER(env); | |
397 if (debug) printf("detach0 called\n"); | |
398 | |
399 task_t gTask = getTask(env, this_obj); | |
400 mach_port_deallocate(mach_task_self(), gTask); | |
401 id symbolicator = getSymbolicator(env, this_obj); | |
402 if (symbolicator != nil) { | |
403 CFRelease(symbolicator); | |
404 } | |
405 JNF_COCOA_EXIT(env); | |
406 } |