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