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