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