Mercurial > hg > graal-compiler
annotate agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdDebuggerLocal.java @ 8023:758935f7c23f
8006423: SA: NullPointerException in sun.jvm.hotspot.debugger.bsd.BsdThread.getContext(BsdThread.java:67)
Summary: Do not rely on mach thread port names to identify threads from SA
Reviewed-by: dholmes, minqi, rbackman
author | sla |
---|---|
date | Fri, 08 Feb 2013 12:48:24 +0100 |
parents | 8e47bac5643a |
children | 39432a1cefdd |
rev | line source |
---|---|
3960 | 1 /* |
2 * Copyright (c) 2002, 2008, 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 package sun.jvm.hotspot.debugger.bsd; | |
26 | |
27 import java.io.*; | |
28 import java.net.*; | |
29 import java.util.*; | |
30 import sun.jvm.hotspot.debugger.*; | |
31 import sun.jvm.hotspot.debugger.x86.*; | |
32 import sun.jvm.hotspot.debugger.cdbg.*; | |
33 import sun.jvm.hotspot.utilities.*; | |
34 import java.lang.reflect.*; | |
35 | |
36 /** <P> An implementation of the JVMDebugger interface. The basic debug | |
37 facilities are implemented through ptrace interface in the JNI code | |
38 (libsaproc.so). Library maps and symbol table management are done in | |
39 JNI. </P> | |
40 | |
41 <P> <B>NOTE</B> that since we have the notion of fetching "Java | |
42 primitive types" from the remote process (which might have | |
43 different sizes than we expect) we have a bootstrapping | |
44 problem. We need to know the sizes of these types before we can | |
45 fetch them. The current implementation solves this problem by | |
46 requiring that it be configured with these type sizes before they | |
47 can be fetched. The readJ(Type) routines here will throw a | |
48 RuntimeException if they are called before the debugger is | |
49 configured with the Java primitive type sizes. </P> */ | |
50 | |
51 public class BsdDebuggerLocal extends DebuggerBase implements BsdDebugger { | |
52 private boolean useGCC32ABI; | |
53 private boolean attached; | |
54 private long p_ps_prochandle; // native debugger handle | |
4006 | 55 private long symbolicator; // macosx symbolicator handle |
56 private long task; // macosx task handle | |
3960 | 57 private boolean isCore; |
58 | |
59 // CDebugger support | |
60 private BsdCDebugger cdbg; | |
61 | |
62 // threadList and loadObjectList are filled by attach0 method | |
63 private List threadList; | |
64 private List loadObjectList; | |
65 | |
66 // called by native method lookupByAddress0 | |
67 private ClosestSymbol createClosestSymbol(String name, long offset) { | |
68 return new ClosestSymbol(name, offset); | |
69 } | |
70 | |
71 // called by native method attach0 | |
72 private LoadObject createLoadObject(String fileName, long textsize, | |
73 long base) { | |
74 File f = new File(fileName); | |
75 Address baseAddr = newAddress(base); | |
76 return new SharedObject(this, fileName, f.length(), baseAddr); | |
77 } | |
78 | |
79 // native methods | |
80 | |
81 private native static void init0() | |
82 throws DebuggerException; | |
83 private native void attach0(int pid) | |
84 throws DebuggerException; | |
85 private native void attach0(String execName, String coreName) | |
86 throws DebuggerException; | |
87 private native void detach0() | |
88 throws DebuggerException; | |
89 private native long lookupByName0(String objectName, String symbol) | |
90 throws DebuggerException; | |
91 private native ClosestSymbol lookupByAddress0(long address) | |
92 throws DebuggerException; | |
8023
758935f7c23f
8006423: SA: NullPointerException in sun.jvm.hotspot.debugger.bsd.BsdThread.getContext(BsdThread.java:67)
sla
parents:
6848
diff
changeset
|
93 private native long[] getThreadIntegerRegisterSet0(long unique_thread_id) |
3960 | 94 throws DebuggerException; |
95 private native byte[] readBytesFromProcess0(long address, long numBytes) | |
96 throws DebuggerException; | |
97 public native static int getAddressSize() ; | |
98 | |
99 // Note on Bsd threads are really processes. When target process is | |
100 // attached by a serviceability agent thread, only that thread can do | |
101 // ptrace operations on the target. This is because from kernel's point | |
102 // view, other threads are just separate processes and they are not | |
103 // attached to the target. When they attempt to make ptrace calls, | |
104 // an ESRCH error will be returned as kernel believes target is not | |
105 // being traced by the caller. | |
106 // To work around the problem, we use a worker thread here to handle | |
107 // all JNI functions that are making ptrace calls. | |
108 | |
109 interface WorkerThreadTask { | |
110 public void doit(BsdDebuggerLocal debugger) throws DebuggerException; | |
111 } | |
112 | |
113 class BsdDebuggerLocalWorkerThread extends Thread { | |
114 BsdDebuggerLocal debugger; | |
115 WorkerThreadTask task; | |
116 DebuggerException lastException; | |
117 | |
118 public BsdDebuggerLocalWorkerThread(BsdDebuggerLocal debugger) { | |
119 this.debugger = debugger; | |
120 setDaemon(true); | |
121 } | |
122 | |
123 public void run() { | |
124 synchronized (workerThread) { | |
125 for (;;) { | |
126 if (task != null) { | |
127 lastException = null; | |
128 try { | |
129 task.doit(debugger); | |
130 } catch (DebuggerException exp) { | |
131 lastException = exp; | |
132 } | |
133 task = null; | |
134 workerThread.notifyAll(); | |
135 } | |
136 | |
137 try { | |
138 workerThread.wait(); | |
139 } catch (InterruptedException x) {} | |
140 } | |
141 } | |
142 } | |
143 | |
144 public WorkerThreadTask execute(WorkerThreadTask task) throws DebuggerException { | |
145 synchronized (workerThread) { | |
146 this.task = task; | |
147 workerThread.notifyAll(); | |
148 while (this.task != null) { | |
149 try { | |
150 workerThread.wait(); | |
151 } catch (InterruptedException x) {} | |
152 } | |
153 if (lastException != null) { | |
154 throw new DebuggerException(lastException); | |
155 } else { | |
156 return task; | |
157 } | |
158 } | |
159 } | |
160 } | |
161 | |
162 private BsdDebuggerLocalWorkerThread workerThread = null; | |
163 | |
164 //---------------------------------------------------------------------- | |
165 // Implementation of Debugger interface | |
166 // | |
167 | |
168 /** <P> machDesc may not be null. </P> | |
169 | |
170 <P> useCache should be set to true if debugging is being done | |
171 locally, and to false if the debugger is being created for the | |
172 purpose of supporting remote debugging. </P> */ | |
173 public BsdDebuggerLocal(MachineDescription machDesc, | |
174 boolean useCache) throws DebuggerException { | |
175 this.machDesc = machDesc; | |
176 utils = new DebuggerUtilities(machDesc.getAddressSize(), | |
177 machDesc.isBigEndian()) { | |
178 public void checkAlignment(long address, long alignment) { | |
179 // Need to override default checkAlignment because we need to | |
180 // relax alignment constraints on Bsd/x86 | |
181 if ( (address % alignment != 0) | |
182 &&(alignment != 8 || address % 4 != 0)) { | |
183 throw new UnalignedAddressException( | |
184 "Trying to read at address: " | |
185 + addressValueToString(address) | |
186 + " with alignment: " + alignment, | |
187 address); | |
188 } | |
189 } | |
190 }; | |
191 | |
192 if (useCache) { | |
193 // FIXME: re-test necessity of cache on Bsd, where data | |
194 // fetching is faster | |
195 // Cache portion of the remote process's address space. | |
196 // Fetching data over the socket connection to dbx is slow. | |
197 // Might be faster if we were using a binary protocol to talk to | |
198 // dbx, but would have to test. For now, this cache works best | |
199 // if it covers the entire heap of the remote process. FIXME: at | |
200 // least should make this tunable from the outside, i.e., via | |
201 // the UI. This is a cache of 4096 4K pages, or 16 MB. The page | |
202 // size must be adjusted to be the hardware's page size. | |
203 // (FIXME: should pick this up from the debugger.) | |
204 if (getCPU().equals("ia64")) { | |
205 initCache(16384, parseCacheNumPagesProperty(1024)); | |
206 } else { | |
207 initCache(4096, parseCacheNumPagesProperty(4096)); | |
208 } | |
209 } | |
210 | |
211 workerThread = new BsdDebuggerLocalWorkerThread(this); | |
212 workerThread.start(); | |
213 } | |
214 | |
215 /** From the Debugger interface via JVMDebugger */ | |
216 public boolean hasProcessList() throws DebuggerException { | |
217 return false; | |
218 } | |
219 | |
220 /** From the Debugger interface via JVMDebugger */ | |
221 public List getProcessList() throws DebuggerException { | |
222 throw new DebuggerException("getProcessList not implemented yet"); | |
223 } | |
224 | |
225 private void checkAttached() throws DebuggerException { | |
226 if (attached) { | |
227 if (isCore) { | |
228 throw new DebuggerException("attached to a core dump already"); | |
229 } else { | |
230 throw new DebuggerException("attached to a process already"); | |
231 } | |
232 } | |
233 } | |
234 | |
235 private void requireAttach() { | |
236 if (! attached) { | |
237 throw new RuntimeException("not attached to a process or a core!"); | |
238 } | |
239 } | |
240 | |
241 /* called from attach methods */ | |
242 private void findABIVersion() throws DebuggerException { | |
243 if (lookupByName0("libjvm.so", "__vt_10JavaThread") != 0 || | |
244 lookupByName0("libjvm_g.so", "__vt_10JavaThread") != 0) { | |
245 // old C++ ABI | |
246 useGCC32ABI = false; | |
247 } else { | |
248 // new C++ ABI | |
249 useGCC32ABI = true; | |
250 } | |
251 } | |
252 | |
253 /** From the Debugger interface via JVMDebugger */ | |
254 public synchronized void attach(int processID) throws DebuggerException { | |
255 checkAttached(); | |
256 threadList = new ArrayList(); | |
257 loadObjectList = new ArrayList(); | |
258 class AttachTask implements WorkerThreadTask { | |
259 int pid; | |
260 public void doit(BsdDebuggerLocal debugger) { | |
261 debugger.attach0(pid); | |
262 debugger.attached = true; | |
263 debugger.isCore = false; | |
264 findABIVersion(); | |
265 } | |
266 } | |
267 | |
268 AttachTask task = new AttachTask(); | |
269 task.pid = processID; | |
270 workerThread.execute(task); | |
271 } | |
272 | |
273 /** From the Debugger interface via JVMDebugger */ | |
274 public synchronized void attach(String execName, String coreName) { | |
275 checkAttached(); | |
276 threadList = new ArrayList(); | |
277 loadObjectList = new ArrayList(); | |
278 attach0(execName, coreName); | |
279 attached = true; | |
280 isCore = true; | |
281 findABIVersion(); | |
282 } | |
283 | |
284 /** From the Debugger interface via JVMDebugger */ | |
285 public synchronized boolean detach() { | |
286 if (!attached) { | |
287 return false; | |
288 } | |
289 | |
290 threadList = null; | |
291 loadObjectList = null; | |
292 | |
293 if (isCore) { | |
294 detach0(); | |
295 attached = false; | |
296 return true; | |
297 } else { | |
298 class DetachTask implements WorkerThreadTask { | |
299 boolean result = false; | |
300 | |
301 public void doit(BsdDebuggerLocal debugger) { | |
302 debugger.detach0(); | |
303 debugger.attached = false; | |
304 result = true; | |
305 } | |
306 } | |
307 | |
308 DetachTask task = new DetachTask(); | |
309 workerThread.execute(task); | |
310 return task.result; | |
311 } | |
312 } | |
313 | |
314 /** From the Debugger interface via JVMDebugger */ | |
315 public Address parseAddress(String addressString) | |
316 throws NumberFormatException { | |
317 long addr = utils.scanAddress(addressString); | |
318 if (addr == 0) { | |
319 return null; | |
320 } | |
321 return new BsdAddress(this, addr); | |
322 } | |
323 | |
324 /** From the Debugger interface via JVMDebugger */ | |
325 public String getOS() { | |
326 return PlatformInfo.getOS(); | |
327 } | |
328 | |
329 /** From the Debugger interface via JVMDebugger */ | |
330 public String getCPU() { | |
331 return PlatformInfo.getCPU(); | |
332 } | |
333 | |
334 public boolean hasConsole() throws DebuggerException { | |
335 return false; | |
336 } | |
337 | |
338 public String consoleExecuteCommand(String cmd) throws DebuggerException { | |
339 throw new DebuggerException("No debugger console available on Bsd"); | |
340 } | |
341 | |
342 public String getConsolePrompt() throws DebuggerException { | |
343 return null; | |
344 } | |
345 | |
346 /* called from lookup */ | |
347 private long handleGCC32ABI(long addr, String symbol) throws DebuggerException { | |
348 if (useGCC32ABI && symbol.startsWith("_ZTV")) { | |
349 return addr + (2 * machDesc.getAddressSize()); | |
350 } else { | |
351 return addr; | |
352 } | |
353 } | |
354 | |
355 /** From the SymbolLookup interface via Debugger and JVMDebugger */ | |
356 public synchronized Address lookup(String objectName, String symbol) { | |
357 requireAttach(); | |
358 if (!attached) { | |
359 return null; | |
360 } | |
361 | |
362 if (isCore) { | |
363 long addr = lookupByName0(objectName, symbol); | |
364 return (addr == 0)? null : new BsdAddress(this, handleGCC32ABI(addr, symbol)); | |
365 } else { | |
366 class LookupByNameTask implements WorkerThreadTask { | |
367 String objectName, symbol; | |
368 Address result; | |
369 | |
370 public void doit(BsdDebuggerLocal debugger) { | |
371 long addr = debugger.lookupByName0(objectName, symbol); | |
372 result = (addr == 0 ? null : new BsdAddress(debugger, handleGCC32ABI(addr, symbol))); | |
373 } | |
374 } | |
375 | |
376 LookupByNameTask task = new LookupByNameTask(); | |
377 task.objectName = objectName; | |
378 task.symbol = symbol; | |
379 workerThread.execute(task); | |
380 return task.result; | |
381 } | |
382 } | |
383 | |
384 /** From the SymbolLookup interface via Debugger and JVMDebugger */ | |
385 public synchronized OopHandle lookupOop(String objectName, String symbol) { | |
386 Address addr = lookup(objectName, symbol); | |
387 if (addr == null) { | |
388 return null; | |
389 } | |
390 return addr.addOffsetToAsOopHandle(0); | |
391 } | |
392 | |
393 /** From the Debugger interface */ | |
394 public MachineDescription getMachineDescription() { | |
395 return machDesc; | |
396 } | |
397 | |
398 //---------------------------------------------------------------------- | |
399 // Implementation of ThreadAccess interface | |
400 // | |
401 | |
402 /** From the ThreadAccess interface via Debugger and JVMDebugger */ | |
8023
758935f7c23f
8006423: SA: NullPointerException in sun.jvm.hotspot.debugger.bsd.BsdThread.getContext(BsdThread.java:67)
sla
parents:
6848
diff
changeset
|
403 public ThreadProxy getThreadForIdentifierAddress(Address threadIdAddr, Address uniqueThreadIdAddr) { |
758935f7c23f
8006423: SA: NullPointerException in sun.jvm.hotspot.debugger.bsd.BsdThread.getContext(BsdThread.java:67)
sla
parents:
6848
diff
changeset
|
404 return new BsdThread(this, threadIdAddr, uniqueThreadIdAddr); |
758935f7c23f
8006423: SA: NullPointerException in sun.jvm.hotspot.debugger.bsd.BsdThread.getContext(BsdThread.java:67)
sla
parents:
6848
diff
changeset
|
405 } |
758935f7c23f
8006423: SA: NullPointerException in sun.jvm.hotspot.debugger.bsd.BsdThread.getContext(BsdThread.java:67)
sla
parents:
6848
diff
changeset
|
406 @Override |
3960 | 407 public ThreadProxy getThreadForIdentifierAddress(Address addr) { |
8023
758935f7c23f
8006423: SA: NullPointerException in sun.jvm.hotspot.debugger.bsd.BsdThread.getContext(BsdThread.java:67)
sla
parents:
6848
diff
changeset
|
408 throw new RuntimeException("unimplemented"); |
3960 | 409 } |
410 | |
8023
758935f7c23f
8006423: SA: NullPointerException in sun.jvm.hotspot.debugger.bsd.BsdThread.getContext(BsdThread.java:67)
sla
parents:
6848
diff
changeset
|
411 |
3960 | 412 /** From the ThreadAccess interface via Debugger and JVMDebugger */ |
413 public ThreadProxy getThreadForThreadId(long id) { | |
414 return new BsdThread(this, id); | |
415 } | |
416 | |
417 //---------------------------------------------------------------------- | |
418 // Internal routines (for implementation of BsdAddress). | |
419 // These must not be called until the MachineDescription has been set up. | |
420 // | |
421 | |
422 /** From the BsdDebugger interface */ | |
423 public String addressValueToString(long address) { | |
424 return utils.addressValueToString(address); | |
425 } | |
426 | |
427 /** From the BsdDebugger interface */ | |
428 public BsdAddress readAddress(long address) | |
429 throws UnmappedAddressException, UnalignedAddressException { | |
430 long value = readAddressValue(address); | |
431 return (value == 0 ? null : new BsdAddress(this, value)); | |
432 } | |
433 public BsdAddress readCompOopAddress(long address) | |
434 throws UnmappedAddressException, UnalignedAddressException { | |
435 long value = readCompOopAddressValue(address); | |
436 return (value == 0 ? null : new BsdAddress(this, value)); | |
437 } | |
438 | |
6848
8e47bac5643a
7054512: Compress class pointers after perm gen removal
roland
parents:
4006
diff
changeset
|
439 public BsdAddress readCompKlassAddress(long address) |
8e47bac5643a
7054512: Compress class pointers after perm gen removal
roland
parents:
4006
diff
changeset
|
440 throws UnmappedAddressException, UnalignedAddressException { |
8e47bac5643a
7054512: Compress class pointers after perm gen removal
roland
parents:
4006
diff
changeset
|
441 long value = readCompKlassAddressValue(address); |
8e47bac5643a
7054512: Compress class pointers after perm gen removal
roland
parents:
4006
diff
changeset
|
442 return (value == 0 ? null : new BsdAddress(this, value)); |
8e47bac5643a
7054512: Compress class pointers after perm gen removal
roland
parents:
4006
diff
changeset
|
443 } |
8e47bac5643a
7054512: Compress class pointers after perm gen removal
roland
parents:
4006
diff
changeset
|
444 |
3960 | 445 /** From the BsdDebugger interface */ |
446 public BsdOopHandle readOopHandle(long address) | |
447 throws UnmappedAddressException, UnalignedAddressException, | |
448 NotInHeapException { | |
449 long value = readAddressValue(address); | |
450 return (value == 0 ? null : new BsdOopHandle(this, value)); | |
451 } | |
452 public BsdOopHandle readCompOopHandle(long address) | |
453 throws UnmappedAddressException, UnalignedAddressException, | |
454 NotInHeapException { | |
455 long value = readCompOopAddressValue(address); | |
456 return (value == 0 ? null : new BsdOopHandle(this, value)); | |
457 } | |
458 | |
459 //---------------------------------------------------------------------- | |
460 // Thread context access | |
461 // | |
462 | |
8023
758935f7c23f
8006423: SA: NullPointerException in sun.jvm.hotspot.debugger.bsd.BsdThread.getContext(BsdThread.java:67)
sla
parents:
6848
diff
changeset
|
463 public synchronized long[] getThreadIntegerRegisterSet(long unique_thread_id) |
3960 | 464 throws DebuggerException { |
465 requireAttach(); | |
466 if (isCore) { | |
8023
758935f7c23f
8006423: SA: NullPointerException in sun.jvm.hotspot.debugger.bsd.BsdThread.getContext(BsdThread.java:67)
sla
parents:
6848
diff
changeset
|
467 return getThreadIntegerRegisterSet0(unique_thread_id); |
3960 | 468 } else { |
469 class GetThreadIntegerRegisterSetTask implements WorkerThreadTask { | |
8023
758935f7c23f
8006423: SA: NullPointerException in sun.jvm.hotspot.debugger.bsd.BsdThread.getContext(BsdThread.java:67)
sla
parents:
6848
diff
changeset
|
470 long unique_thread_id; |
3960 | 471 long[] result; |
472 public void doit(BsdDebuggerLocal debugger) { | |
8023
758935f7c23f
8006423: SA: NullPointerException in sun.jvm.hotspot.debugger.bsd.BsdThread.getContext(BsdThread.java:67)
sla
parents:
6848
diff
changeset
|
473 result = debugger.getThreadIntegerRegisterSet0(unique_thread_id); |
3960 | 474 } |
475 } | |
476 | |
477 GetThreadIntegerRegisterSetTask task = new GetThreadIntegerRegisterSetTask(); | |
8023
758935f7c23f
8006423: SA: NullPointerException in sun.jvm.hotspot.debugger.bsd.BsdThread.getContext(BsdThread.java:67)
sla
parents:
6848
diff
changeset
|
478 task.unique_thread_id = unique_thread_id; |
3960 | 479 workerThread.execute(task); |
480 return task.result; | |
481 } | |
482 } | |
483 | |
484 /** Need to override this to relax alignment checks on x86. */ | |
485 public long readCInteger(long address, long numBytes, boolean isUnsigned) | |
486 throws UnmappedAddressException, UnalignedAddressException { | |
487 // Only slightly relaxed semantics -- this is a hack, but is | |
488 // necessary on x86 where it seems the compiler is | |
489 // putting some global 64-bit data on 32-bit boundaries | |
490 if (numBytes == 8) { | |
491 utils.checkAlignment(address, 4); | |
492 } else { | |
493 utils.checkAlignment(address, numBytes); | |
494 } | |
495 byte[] data = readBytes(address, numBytes); | |
496 return utils.dataToCInteger(data, isUnsigned); | |
497 } | |
498 | |
499 // Overridden from DebuggerBase because we need to relax alignment | |
500 // constraints on x86 | |
501 public long readJLong(long address) | |
502 throws UnmappedAddressException, UnalignedAddressException { | |
503 utils.checkAlignment(address, jintSize); | |
504 byte[] data = readBytes(address, jlongSize); | |
505 return utils.dataToJLong(data, jlongSize); | |
506 } | |
507 | |
508 //---------------------------------------------------------------------- | |
509 // Address access. Can not be package private, but should only be | |
510 // accessed by the architecture-specific subpackages. | |
511 | |
512 /** From the BsdDebugger interface */ | |
513 public long getAddressValue(Address addr) { | |
514 if (addr == null) return 0; | |
515 return ((BsdAddress) addr).getValue(); | |
516 } | |
517 | |
518 /** From the BsdDebugger interface */ | |
519 public Address newAddress(long value) { | |
520 if (value == 0) return null; | |
521 return new BsdAddress(this, value); | |
522 } | |
523 | |
524 /** From the BsdCDebugger interface */ | |
525 public List/*<ThreadProxy>*/ getThreadList() { | |
526 requireAttach(); | |
527 return threadList; | |
528 } | |
529 | |
530 /** From the BsdCDebugger interface */ | |
531 public List/*<LoadObject>*/ getLoadObjectList() { | |
532 requireAttach(); | |
533 return loadObjectList; | |
534 } | |
535 | |
536 /** From the BsdCDebugger interface */ | |
537 public synchronized ClosestSymbol lookup(long addr) { | |
538 requireAttach(); | |
539 if (isCore) { | |
540 return lookupByAddress0(addr); | |
541 } else { | |
542 class LookupByAddressTask implements WorkerThreadTask { | |
543 long addr; | |
544 ClosestSymbol result; | |
545 | |
546 public void doit(BsdDebuggerLocal debugger) { | |
547 result = debugger.lookupByAddress0(addr); | |
548 } | |
549 } | |
550 | |
551 LookupByAddressTask task = new LookupByAddressTask(); | |
552 task.addr = addr; | |
553 workerThread.execute(task); | |
554 return task.result; | |
555 } | |
556 } | |
557 | |
558 public CDebugger getCDebugger() { | |
559 if (cdbg == null) { | |
560 String cpu = getCPU(); | |
561 if (cpu.equals("ia64") ) { | |
562 // IA-64 is not supported because of stack-walking issues | |
563 return null; | |
564 } | |
565 cdbg = new BsdCDebugger(this); | |
566 } | |
567 return cdbg; | |
568 } | |
569 | |
570 /** This reads bytes from the remote process. */ | |
571 public synchronized ReadResult readBytesFromProcess(long address, | |
572 long numBytes) throws UnmappedAddressException, DebuggerException { | |
573 requireAttach(); | |
574 if (isCore) { | |
575 byte[] res = readBytesFromProcess0(address, numBytes); | |
576 return (res != null)? new ReadResult(res) : new ReadResult(address); | |
577 } else { | |
578 class ReadBytesFromProcessTask implements WorkerThreadTask { | |
579 long address, numBytes; | |
580 ReadResult result; | |
581 public void doit(BsdDebuggerLocal debugger) { | |
582 byte[] res = debugger.readBytesFromProcess0(address, numBytes); | |
583 if (res != null) | |
584 result = new ReadResult(res); | |
585 else | |
586 result = new ReadResult(address); | |
587 } | |
588 } | |
589 | |
590 ReadBytesFromProcessTask task = new ReadBytesFromProcessTask(); | |
591 task.address = address; | |
592 task.numBytes = numBytes; | |
593 workerThread.execute(task); | |
594 return task.result; | |
595 } | |
596 } | |
597 | |
598 public void writeBytesToProcess(long address, long numBytes, byte[] data) | |
599 throws UnmappedAddressException, DebuggerException { | |
600 // FIXME | |
601 throw new DebuggerException("Unimplemented"); | |
602 } | |
603 | |
604 static { | |
605 System.loadLibrary("saproc"); | |
606 init0(); | |
607 } | |
608 } |