Mercurial > hg > truffle
comparison agent/src/share/classes/sun/jvm/hotspot/debugger/proc/ProcDebuggerLocal.java @ 0:a61af66fc99e jdk7-b24
Initial load
author | duke |
---|---|
date | Sat, 01 Dec 2007 00:00:00 +0000 |
parents | |
children | ba764ed4b6f2 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:a61af66fc99e |
---|---|
1 /* | |
2 * Copyright 2002-2004 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, | |
20 * CA 95054 USA or visit www.sun.com if you need additional information or | |
21 * have any questions. | |
22 * | |
23 */ | |
24 | |
25 package sun.jvm.hotspot.debugger.proc; | |
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.cdbg.*; | |
32 import sun.jvm.hotspot.debugger.proc.amd64.*; | |
33 import sun.jvm.hotspot.debugger.proc.sparc.*; | |
34 import sun.jvm.hotspot.debugger.proc.x86.*; | |
35 import sun.jvm.hotspot.debugger.amd64.*; | |
36 import sun.jvm.hotspot.debugger.sparc.*; | |
37 import sun.jvm.hotspot.debugger.x86.*; | |
38 import sun.jvm.hotspot.utilities.*; | |
39 | |
40 /** <P> An implementation of the JVMDebugger interface which sits on | |
41 * top of proc and relies on the SA's proc import module for | |
42 * communication with the debugger. </P> | |
43 * | |
44 * <P> <B>NOTE</B> that since we have the notion of fetching "Java | |
45 * primitive types" from the remote process (which might have | |
46 * different sizes than we expect) we have a bootstrapping | |
47 * problem. We need to know the sizes of these types before we can | |
48 * fetch them. The current implementation solves this problem by | |
49 * requiring that it be configured with these type sizes before they | |
50 * can be fetched. The readJ(Type) routines here will throw a | |
51 * RuntimeException if they are called before the debugger is | |
52 * configured with the Java primitive type sizes. </P> | |
53 */ | |
54 | |
55 public class ProcDebuggerLocal extends DebuggerBase implements ProcDebugger { | |
56 | |
57 | |
58 protected static final int cacheSize = 16 * 1024 * 1024; // 16 MB | |
59 | |
60 //------------------------------------------------------------------------ | |
61 // Implementation of Debugger interface | |
62 // | |
63 | |
64 /** <P> machDesc may be null if it couldn't be determined yet; i.e., | |
65 * if we're on SPARC, we need to ask the remote process whether | |
66 * we're in 32- or 64-bit mode. </P> | |
67 * | |
68 * <P> useCache should be set to true if debugging is being done | |
69 * locally, and to false if the debugger is being created for the | |
70 * purpose of supporting remote debugging. </P> */ | |
71 public ProcDebuggerLocal(MachineDescription machDesc, boolean useCache) { | |
72 this.machDesc = machDesc; | |
73 int cacheNumPages; | |
74 int cachePageSize; | |
75 | |
76 final String cpu = PlatformInfo.getCPU(); | |
77 if (cpu.equals("sparc")) { | |
78 threadFactory = new ProcSPARCThreadFactory(this); | |
79 pcRegIndex = SPARCThreadContext.R_PC; | |
80 fpRegIndex = SPARCThreadContext.R_I6; | |
81 } else if (cpu.equals("x86")) { | |
82 threadFactory = new ProcX86ThreadFactory(this); | |
83 pcRegIndex = X86ThreadContext.EIP; | |
84 fpRegIndex = X86ThreadContext.EBP; | |
85 unalignedAccessesOkay = true; | |
86 } else if (cpu.equals("amd64")) { | |
87 threadFactory = new ProcAMD64ThreadFactory(this); | |
88 pcRegIndex = AMD64ThreadContext.RIP; | |
89 fpRegIndex = AMD64ThreadContext.RBP; | |
90 } else { | |
91 throw new RuntimeException("Thread access for CPU architecture " + PlatformInfo.getCPU() + " not yet supported"); | |
92 } | |
93 if (useCache) { | |
94 // Cache portion of the remote process's address space. | |
95 // For now, this cache works best if it covers the entire | |
96 // heap of the remote process. FIXME: at least should make this | |
97 // tunable from the outside, i.e., via the UI. This is a 16 MB | |
98 // cache divided on SPARC into 2048 8K pages and on x86 into | |
99 // 4096 4K pages; the page size must be adjusted to be the OS's | |
100 // page size. | |
101 | |
102 cachePageSize = getPageSize(); | |
103 cacheNumPages = parseCacheNumPagesProperty(cacheSize / cachePageSize); | |
104 initCache(cachePageSize, cacheNumPages); | |
105 } | |
106 | |
107 resetNativePointers(); | |
108 clearCacheFields(); | |
109 } | |
110 | |
111 /** FIXME: implement this with a Runtime.exec() of ps followed by | |
112 * parsing of its output */ | |
113 public boolean hasProcessList() throws DebuggerException { | |
114 return false; | |
115 } | |
116 | |
117 public List getProcessList() throws DebuggerException { | |
118 throw new DebuggerException("Not yet supported"); | |
119 } | |
120 | |
121 | |
122 /** From the Debugger interface via JVMDebugger */ | |
123 public synchronized void attach(int processID) throws DebuggerException { | |
124 checkAttached(); | |
125 isCore = false; | |
126 attach0(new Integer(processID).toString()); | |
127 attached = true; | |
128 suspended = true; | |
129 } | |
130 | |
131 /** From the Debugger interface via JVMDebugger */ | |
132 public synchronized void attach | |
133 (String executableName, String coreFileName) throws DebuggerException { | |
134 checkAttached(); | |
135 isCore = true; | |
136 topFrameCache = new HashMap(); | |
137 attach0(executableName, coreFileName); | |
138 attached = true; | |
139 suspended = true; | |
140 } | |
141 | |
142 /** From the Debugger interface via JVMDebugger */ | |
143 public synchronized boolean detach() { | |
144 if (! attached) { | |
145 return false; | |
146 } | |
147 | |
148 try { | |
149 if (p_ps_prochandle == 0L) { | |
150 return false; | |
151 } | |
152 detach0(); | |
153 clearCache(); | |
154 return true; | |
155 } catch (Exception e) { | |
156 e.printStackTrace(); | |
157 return false; | |
158 } finally { | |
159 resetNativePointers(); | |
160 clearCacheFields(); | |
161 suspended = false; | |
162 attached = false; | |
163 } | |
164 } | |
165 | |
166 public synchronized void suspend() throws DebuggerException { | |
167 requireAttach(); | |
168 if (suspended) { | |
169 throw new DebuggerException("Process already suspended"); | |
170 } | |
171 suspend0(); | |
172 suspended = true; | |
173 enableCache(); | |
174 reresolveLoadObjects(); | |
175 } | |
176 | |
177 public synchronized void resume() throws DebuggerException { | |
178 requireAttach(); | |
179 if (!suspended) { | |
180 throw new DebuggerException("Process not suspended"); | |
181 } | |
182 resume0(); | |
183 disableCache(); | |
184 suspended = false; | |
185 } | |
186 | |
187 public synchronized boolean isSuspended() throws DebuggerException { | |
188 requireAttach(); | |
189 return suspended; | |
190 } | |
191 | |
192 /** From the Debugger interface via JVMDebugger */ | |
193 public Address parseAddress(String addressString) throws NumberFormatException { | |
194 long addr = utils.scanAddress(addressString); | |
195 if (addr == 0) { | |
196 return null; | |
197 } | |
198 return new ProcAddress(this, addr); | |
199 } | |
200 | |
201 /** From the Debugger interface via JVMDebugger */ | |
202 public String getOS() { | |
203 return PlatformInfo.getOS(); | |
204 } | |
205 | |
206 /** From the Debugger interface via JVMDebugger */ | |
207 public String getCPU() { | |
208 return PlatformInfo.getCPU(); | |
209 } | |
210 | |
211 public boolean hasConsole() throws DebuggerException { | |
212 return false; | |
213 } | |
214 | |
215 public String consoleExecuteCommand(String cmd) throws DebuggerException { | |
216 throw new DebuggerException("Can't execute console commands"); | |
217 } | |
218 | |
219 public String getConsolePrompt() throws DebuggerException { | |
220 return ""; | |
221 } | |
222 | |
223 public CDebugger getCDebugger() throws DebuggerException { | |
224 if (cdbg == null) { | |
225 cdbg = new ProcCDebugger(this); | |
226 } | |
227 return cdbg; | |
228 } | |
229 | |
230 /** From the SymbolLookup interface via Debugger and JVMDebugger */ | |
231 public synchronized Address lookup(String objectName, String symbol) { | |
232 requireAttach(); | |
233 long addr = lookupByName0(objectName, symbol); | |
234 if (addr == 0) { | |
235 return null; | |
236 } | |
237 return new ProcAddress(this, addr); | |
238 } | |
239 | |
240 /** From the SymbolLookup interface via Debugger and JVMDebugger */ | |
241 public synchronized OopHandle lookupOop(String objectName, String symbol) { | |
242 Address addr = lookup(objectName, symbol); | |
243 if (addr == null) { | |
244 return null; | |
245 } | |
246 return addr.addOffsetToAsOopHandle(0); | |
247 } | |
248 | |
249 /** From the ProcDebugger interface */ | |
250 public MachineDescription getMachineDescription() { | |
251 return machDesc; | |
252 } | |
253 | |
254 /** Internal routine supporting lazy setting of MachineDescription, | |
255 * since on SPARC we will need to query the remote process to ask | |
256 * it what its data model is (32- or 64-bit). | |
257 */ | |
258 | |
259 public void setMachineDescription(MachineDescription machDesc) { | |
260 this.machDesc = machDesc; | |
261 setBigEndian(machDesc.isBigEndian()); | |
262 utils = new DebuggerUtilities(machDesc.getAddressSize(), machDesc.isBigEndian()); | |
263 } | |
264 | |
265 public synchronized int getRemoteProcessAddressSize() | |
266 throws DebuggerException { | |
267 requireAttach(); | |
268 return getRemoteProcessAddressSize0(); | |
269 } | |
270 | |
271 //-------------------------------------------------------------------------------- | |
272 // Implementation of ThreadAccess interface | |
273 // | |
274 | |
275 /** From the ThreadAccess interface via Debugger and JVMDebugger */ | |
276 public ThreadProxy getThreadForIdentifierAddress(Address addr) { | |
277 return threadFactory.createThreadWrapper(addr); | |
278 } | |
279 | |
280 public ThreadProxy getThreadForThreadId(long id) { | |
281 return threadFactory.createThreadWrapper(id); | |
282 } | |
283 | |
284 //---------------------------------------------------------------------- | |
285 // Overridden from DebuggerBase because we need to relax alignment | |
286 // constraints on x86 | |
287 | |
288 public long readJLong(long address) | |
289 throws UnmappedAddressException, UnalignedAddressException { | |
290 checkJavaConfigured(); | |
291 // FIXME: allow this to be configurable. Undesirable to add a | |
292 // dependency on the runtime package here, though, since this | |
293 // package should be strictly underneath it. | |
294 if (unalignedAccessesOkay) { | |
295 utils.checkAlignment(address, jintSize); | |
296 } else { | |
297 utils.checkAlignment(address, jlongSize); | |
298 } | |
299 byte[] data = readBytes(address, jlongSize); | |
300 return utils.dataToJLong(data, jlongSize); | |
301 } | |
302 | |
303 //-------------------------------------------------------------------------------- | |
304 // Internal routines (for implementation of ProcAddress). | |
305 // These must not be called until the MachineDescription has been set up. | |
306 // | |
307 | |
308 /** From the ProcDebugger interface */ | |
309 public String addressValueToString(long address) { | |
310 return utils.addressValueToString(address); | |
311 } | |
312 | |
313 /** Need to override this to relax alignment checks on Solaris/x86. */ | |
314 public long readCInteger(long address, long numBytes, boolean isUnsigned) | |
315 throws UnmappedAddressException, UnalignedAddressException { | |
316 checkConfigured(); | |
317 if (!unalignedAccessesOkay) { | |
318 utils.checkAlignment(address, numBytes); | |
319 } else { | |
320 // Only slightly relaxed semantics -- this is a hack, but is | |
321 // necessary on Solaris/x86 where it seems the compiler is | |
322 // putting some global 64-bit data on 32-bit boundaries | |
323 if (numBytes == 8) { | |
324 utils.checkAlignment(address, 4); | |
325 } else { | |
326 utils.checkAlignment(address, numBytes); | |
327 } | |
328 } | |
329 byte[] data = readBytes(address, numBytes); | |
330 return utils.dataToCInteger(data, isUnsigned); | |
331 } | |
332 | |
333 /** From the ProcDebugger interface */ | |
334 public ProcAddress readAddress(long address) | |
335 throws UnmappedAddressException, UnalignedAddressException { | |
336 long value = readAddressValue(address); | |
337 return (value == 0 ? null : new ProcAddress(this, value)); | |
338 } | |
339 | |
340 /** From the ProcDebugger interface */ | |
341 public ProcOopHandle readOopHandle(long address) | |
342 throws UnmappedAddressException, UnalignedAddressException, NotInHeapException { | |
343 long value = readAddressValue(address); | |
344 return (value == 0 ? null : new ProcOopHandle(this, value)); | |
345 } | |
346 | |
347 public void writeBytesToProcess(long address, long numBytes, byte[] data) | |
348 throws UnmappedAddressException, DebuggerException { | |
349 if (isCore) { | |
350 throw new DebuggerException("Attached to a core file!"); | |
351 } | |
352 writeBytesToProcess0(address, numBytes, data); | |
353 } | |
354 | |
355 public synchronized ReadResult readBytesFromProcess(long address, long numBytes) | |
356 throws DebuggerException { | |
357 requireAttach(); | |
358 byte[] res = readBytesFromProcess0(address, numBytes); | |
359 if(res != null) | |
360 return new ReadResult(res); | |
361 else | |
362 return new ReadResult(address); | |
363 } | |
364 | |
365 protected int getPageSize() { | |
366 int pagesize = getPageSize0(); | |
367 if (pagesize == -1) { | |
368 // return the hard coded default value. | |
369 pagesize = (PlatformInfo.getCPU().equals("x86"))? 4096 : 8192; | |
370 } | |
371 return pagesize; | |
372 } | |
373 | |
374 //-------------------------------------------------------------------------------- | |
375 // Thread context access. Can not be package private, but should | |
376 // only be accessed by the architecture-specific subpackages. | |
377 | |
378 /** From the ProcDebugger interface. May have to redefine this later. */ | |
379 public synchronized long[] getThreadIntegerRegisterSet(int tid) { | |
380 requireAttach(); | |
381 return getThreadIntegerRegisterSet0(tid); | |
382 } | |
383 | |
384 //-------------------------------------------------------------------------------- | |
385 // Address access. Can not be package private, but should only be | |
386 // accessed by the architecture-specific subpackages. | |
387 | |
388 /** From the ProcDebugger interface */ | |
389 public long getAddressValue(Address addr) { | |
390 if (addr == null) return 0; | |
391 return ((ProcAddress) addr).getValue(); | |
392 } | |
393 | |
394 /** From the ProcDebugger interface */ | |
395 public Address newAddress(long value) { | |
396 if (value == 0) return null; | |
397 return new ProcAddress(this, value); | |
398 } | |
399 | |
400 /** From the ProcDebugger interface */ | |
401 public synchronized List getThreadList() throws DebuggerException { | |
402 requireAttach(); | |
403 List res = null; | |
404 if (isCore && (threadListCache != null)) { | |
405 res = threadListCache; | |
406 } else { | |
407 res = new ArrayList(); | |
408 fillThreadList0(res); | |
409 if (isCore) { | |
410 threadListCache = res; | |
411 } | |
412 } | |
413 return res; | |
414 } | |
415 | |
416 /** From the ProcDebugger interface */ | |
417 public synchronized List getLoadObjectList() throws DebuggerException { | |
418 requireAttach(); | |
419 if (!suspended) { | |
420 throw new DebuggerException("Process not suspended"); | |
421 } | |
422 | |
423 if (loadObjectCache == null) { | |
424 updateLoadObjectCache(); | |
425 } | |
426 return loadObjectCache; | |
427 } | |
428 | |
429 /** From the ProcDebugger interface */ | |
430 public synchronized CFrame topFrameForThread(ThreadProxy thread) | |
431 throws DebuggerException { | |
432 requireAttach(); | |
433 CFrame res = null; | |
434 if (isCore && ((res = (CFrame) topFrameCache.get(thread)) != null)) { | |
435 return res; | |
436 } else { | |
437 ThreadContext context = thread.getContext(); | |
438 int numRegs = context.getNumRegisters(); | |
439 long[] regs = new long[numRegs]; | |
440 for (int i = 0; i < numRegs; i++) { | |
441 regs[i] = context.getRegister(i); | |
442 } | |
443 res = fillCFrameList0(regs); | |
444 if (isCore) { | |
445 topFrameCache.put(thread, res); | |
446 } | |
447 return res; | |
448 } | |
449 } | |
450 | |
451 /** From the ProcDebugger interface */ | |
452 public synchronized ClosestSymbol lookup(long address) { | |
453 requireAttach(); | |
454 return lookupByAddress0(address); | |
455 } | |
456 | |
457 /** From the ProcDebugger interface */ | |
458 public String demangle(String name) { | |
459 return demangle0(name); | |
460 } | |
461 | |
462 //------------- Internals only below this point -------------------- | |
463 // | |
464 // | |
465 | |
466 private void updateLoadObjectCache() { | |
467 List res = new ArrayList(); | |
468 nameToDsoMap = new HashMap(); | |
469 fillLoadObjectList0(res); | |
470 loadObjectCache = sortLoadObjects(res); | |
471 } | |
472 | |
473 // sort load objects by base address | |
474 private static List sortLoadObjects(List in) { | |
475 // sort the list by base address | |
476 Object[] arr = in.toArray(); | |
477 Arrays.sort(arr, loadObjectComparator); | |
478 return Arrays.asList(arr); | |
479 } | |
480 | |
481 private long lookupByName(String objectName, String symbolName) | |
482 throws DebuggerException { | |
483 // NOTE: this assumes that process is suspended (which is probably | |
484 // necessary assumption given that DSOs can be loaded/unloaded as | |
485 // process runs). Should update documentation. | |
486 if (nameToDsoMap == null) { | |
487 getLoadObjectList(); | |
488 } | |
489 SharedObject dso = (SharedObject) nameToDsoMap.get(objectName); | |
490 // The DSO can be null because we use this to search through known | |
491 // DSOs in HotSpotTypeDataBase (for example) | |
492 if (dso != null) { | |
493 ProcAddress addr = (ProcAddress) dso.lookupSymbol(symbolName); | |
494 if (addr != null) { | |
495 return addr.getValue(); | |
496 } | |
497 } | |
498 return 0; | |
499 } | |
500 | |
501 private SharedObject findDSOByName(String fullPathName) { | |
502 if (loadObjectCache == null) | |
503 return null; | |
504 for (Iterator iter = loadObjectCache.iterator(); iter.hasNext(); ) { | |
505 SharedObject dso = (SharedObject) iter.next(); | |
506 if (dso.getName().equals(fullPathName)) { | |
507 return dso; | |
508 } | |
509 } | |
510 return null; | |
511 } | |
512 | |
513 private void reresolveLoadObjects() throws DebuggerException { | |
514 if (loadObjectCache == null) { | |
515 return; | |
516 } | |
517 updateLoadObjectCache(); | |
518 } | |
519 | |
520 | |
521 private void checkAttached() { | |
522 if (attached) { | |
523 if (isCore) { | |
524 throw new DebuggerException("already attached to a core file!"); | |
525 } else { | |
526 throw new DebuggerException("already attached to a process!"); | |
527 } | |
528 } | |
529 } | |
530 | |
531 private void requireAttach() { | |
532 if (! attached) { | |
533 throw new RuntimeException("not attached to a process or core file!"); | |
534 } | |
535 } | |
536 | |
537 private void clearCacheFields() { | |
538 loadObjectCache = null; | |
539 nameToDsoMap = null; | |
540 threadListCache = null; | |
541 topFrameCache = null; | |
542 } | |
543 | |
544 private void resetNativePointers() { | |
545 p_ps_prochandle = 0L; | |
546 | |
547 // reset thread_db pointers | |
548 libthread_db_handle = 0L; | |
549 p_td_thragent_t = 0L; | |
550 p_td_init = 0L; | |
551 p_td_ta_new = 0L; | |
552 p_td_ta_delete = 0L; | |
553 p_td_ta_thr_iter = 0L; | |
554 p_td_thr_get_info = 0L; | |
555 p_td_ta_map_id2thr = 0L; | |
556 p_td_thr_getgregs = 0L; | |
557 | |
558 // part of class sharing workaround | |
559 classes_jsa_fd = -1; | |
560 p_file_map_header = 0L; | |
561 } | |
562 | |
563 // native methods and native helpers | |
564 | |
565 // attach, detach | |
566 private native void attach0(String pid) throws DebuggerException; | |
567 private native void attach0(String executableFile, String coreFileName) throws DebuggerException; | |
568 private native void detach0() throws DebuggerException; | |
569 | |
570 // address size, page size | |
571 private native int getRemoteProcessAddressSize0() throws DebuggerException; | |
572 private native int getPageSize0() throws DebuggerException; | |
573 | |
574 // threads, stacks | |
575 private native long[] getThreadIntegerRegisterSet0(long tid) throws DebuggerException; | |
576 private native void fillThreadList0(List l) throws DebuggerException; | |
577 | |
578 // fills stack frame list given reg set of the top frame and top frame | |
579 private native ProcCFrame fillCFrameList0(long[] regs) throws DebuggerException; | |
580 | |
581 // helper called by fillCFrameList0 | |
582 private ProcCFrame createSenderFrame(ProcCFrame f, long pc, long fp) { | |
583 ProcCFrame sender = new ProcCFrame(this, newAddress(pc), newAddress(fp)); | |
584 if (f != null) { | |
585 f.setSender(sender); | |
586 } | |
587 return sender; | |
588 } | |
589 | |
590 // shared objects | |
591 private native void fillLoadObjectList0(List l) throws DebuggerException; | |
592 | |
593 // helper called by fillLoadObjectList0 | |
594 private LoadObject createLoadObject(String fileName, long textsize, long base) { | |
595 File f = new File(fileName); | |
596 Address baseAddr = newAddress(base); | |
597 SharedObject res = findDSOByName(fileName); | |
598 if (res != null) { | |
599 // already in cache. just change the base, if needed | |
600 Address oldBase = res.getBase(); | |
601 if (! baseAddr.equals(oldBase)) { | |
602 res.setBase(baseAddr); | |
603 } | |
604 } else { | |
605 // new shared object. | |
606 res = new SharedObject(this, fileName, f.length(), baseAddr); | |
607 } | |
608 nameToDsoMap.put(f.getName(), res); | |
609 return res; | |
610 } | |
611 | |
612 // symbol-to-pc | |
613 private native long lookupByName0(String objectName, String symbolName) throws DebuggerException; | |
614 private native ClosestSymbol lookupByAddress0(long address) throws DebuggerException; | |
615 | |
616 // helper called by lookupByAddress0 | |
617 private ClosestSymbol createClosestSymbol(String name, long offset) { | |
618 return new ClosestSymbol(name, offset); | |
619 } | |
620 | |
621 // process read/write | |
622 private native byte[] readBytesFromProcess0(long address, long numBytes) throws DebuggerException; | |
623 private native void writeBytesToProcess0(long address, long numBytes, byte[] data) throws DebuggerException; | |
624 | |
625 // process control | |
626 private native void suspend0() throws DebuggerException; | |
627 private native void resume0() throws DebuggerException; | |
628 | |
629 // demangle a C++ name | |
630 private native String demangle0(String name); | |
631 | |
632 // init JNI ids to fields, methods | |
633 private native static void initIDs() throws DebuggerException; | |
634 private static LoadObjectComparator loadObjectComparator; | |
635 | |
636 static { | |
637 System.loadLibrary("saproc"); | |
638 initIDs(); | |
639 loadObjectComparator = new LoadObjectComparator(); | |
640 } | |
641 | |
642 private boolean unalignedAccessesOkay; | |
643 private ProcThreadFactory threadFactory; | |
644 | |
645 // indices of PC and FP registers in gregset | |
646 private int pcRegIndex; | |
647 private int fpRegIndex; | |
648 | |
649 // Symbol lookup support | |
650 // This is a map of library names to DSOs | |
651 private Map nameToDsoMap; // Map<String, SharedObject> | |
652 | |
653 // C/C++ debugging support | |
654 private List/*<LoadObject>*/ loadObjects; | |
655 private CDebugger cdbg; | |
656 | |
657 // ProcessControl support | |
658 private boolean suspended; | |
659 | |
660 // libproc handle | |
661 private long p_ps_prochandle; | |
662 | |
663 // libthread.so's dlopen handle, thread agent | |
664 // and function pointers | |
665 private long libthread_db_handle; | |
666 private long p_td_thragent_t; | |
667 private long p_td_init; | |
668 private long p_td_ta_new; | |
669 private long p_td_ta_delete; | |
670 private long p_td_ta_thr_iter; | |
671 private long p_td_thr_get_info; | |
672 private long p_td_ta_map_id2thr; | |
673 private long p_td_thr_getgregs; | |
674 | |
675 // part of class sharing workaround | |
676 private int classes_jsa_fd; | |
677 private long p_file_map_header; | |
678 | |
679 private boolean attached = false; | |
680 private boolean isCore; | |
681 | |
682 // for core files, we cache load object list, thread list, top frames etc. | |
683 // for processes we cache load object list and sync. it during suspend. | |
684 private List threadListCache; | |
685 private List loadObjectCache; | |
686 private Map topFrameCache; // Map<ThreadProxy, CFrame> | |
687 } |