comparison agent/src/share/classes/sun/jvm/hotspot/debugger/DebuggerBase.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 2001-2002 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;
26
27 /** <P> DebuggerBase is a recommended base class for debugger
28 implementations. It can use a PageCache to cache data from the
29 target process. Note that this class would not be suitable if the
30 system were used to reflect upon itself; it would never be safe to
31 store the value in an OopHandle in anything but an OopHandle.
32 However, it provides a fair amount of code sharing to the current
33 dbx and win32 implementations. </P>
34
35 <P> NOTE that much of the code sharing is achieved by having this
36 class implement many of the methods in the Win32Debugger and
37 DbxDebugger interfaces. </P> */
38
39 public abstract class DebuggerBase implements Debugger {
40 // May be set lazily, but must be set before calling any of the read
41 // routines below
42 protected MachineDescription machDesc;
43 protected DebuggerUtilities utils;
44 // Java primitive type sizes, set during bootstrapping. Do not call
45 // any of the Java read routines until these are set up.
46 protected long jbooleanSize;
47 protected long jbyteSize;
48 protected long jcharSize;
49 protected long jdoubleSize;
50 protected long jfloatSize;
51 protected long jintSize;
52 protected long jlongSize;
53 protected long jshortSize;
54 protected boolean javaPrimitiveTypesConfigured;
55 // Should be initialized if desired by calling initCache()
56 private PageCache cache;
57
58 // State for faster accessors that don't allocate memory on each read
59 private boolean useFastAccessors;
60 private boolean bigEndian;
61
62 // Page-fetching functionality for LRU cache
63 class Fetcher implements PageFetcher {
64 public Page fetchPage(long pageBaseAddress, long numBytes) {
65 // This assumes that if any byte is unmapped, that the entire
66 // page is. The common case, however, is that the page is
67 // mapped, so we always fetch the entire thing all at once to
68 // avoid two round-trip communications per page fetch, even
69 // though fetching of unmapped pages will be slow.
70 ReadResult res = readBytesFromProcess(pageBaseAddress, numBytes);
71 if (res.getData() == null) {
72 return new Page(pageBaseAddress, numBytes);
73 }
74 return new Page(pageBaseAddress, res.getData());
75 }
76 }
77
78 protected DebuggerBase() {
79 }
80
81 /** From the JVMDebugger interface. This is the only public method
82 of this class. */
83 public void configureJavaPrimitiveTypeSizes(long jbooleanSize,
84 long jbyteSize,
85 long jcharSize,
86 long jdoubleSize,
87 long jfloatSize,
88 long jintSize,
89 long jlongSize,
90 long jshortSize) {
91 this.jbooleanSize = jbooleanSize;
92 this.jbyteSize = jbyteSize;
93 this.jcharSize = jcharSize;
94 this.jdoubleSize = jdoubleSize;
95 this.jfloatSize = jfloatSize;
96 this.jintSize = jintSize;
97 this.jlongSize = jlongSize;
98 this.jshortSize = jshortSize;
99
100 if (jbooleanSize < 1) {
101 throw new RuntimeException("jboolean size is too small");
102 }
103
104 if (jbyteSize < 1) {
105 throw new RuntimeException("jbyte size is too small");
106 }
107
108 if (jcharSize < 2) {
109 throw new RuntimeException("jchar size is too small");
110 }
111
112 if (jdoubleSize < 8) {
113 throw new RuntimeException("jdouble size is too small");
114 }
115
116 if (jfloatSize < 4) {
117 throw new RuntimeException("jfloat size is too small");
118 }
119
120 if (jintSize < 4) {
121 throw new RuntimeException("jint size is too small");
122 }
123
124 if (jlongSize < 8) {
125 throw new RuntimeException("jlong size is too small");
126 }
127
128 if (jshortSize < 2) {
129 throw new RuntimeException("jshort size is too small");
130 }
131
132 if (jintSize != jfloatSize) {
133 // If dataToJFloat were rewritten, this wouldn't be necessary
134 throw new RuntimeException("jint size and jfloat size must be equal");
135 }
136
137 if (jlongSize != jdoubleSize) {
138 // If dataToJDouble were rewritten, this wouldn't be necessary
139 throw new RuntimeException("jlong size and jdouble size must be equal");
140 }
141
142 useFastAccessors =
143 ((cache != null) &&
144 (jbooleanSize == 1) &&
145 (jbyteSize == 1) &&
146 (jcharSize == 2) &&
147 (jdoubleSize == 8) &&
148 (jfloatSize == 4) &&
149 (jintSize == 4) &&
150 (jlongSize == 8) &&
151 (jshortSize == 2));
152
153 javaPrimitiveTypesConfigured = true;
154 }
155
156 /** May be called by subclasses if desired to initialize the page
157 cache but may not be overridden */
158 protected final void initCache(long pageSize, long maxNumPages) {
159 cache = new PageCache(pageSize, maxNumPages, new Fetcher());
160 if (machDesc != null) {
161 bigEndian = machDesc.isBigEndian();
162 }
163 }
164
165 /** May be called by subclasses if needed (if the machine
166 description is not available at the time of cache
167 initialization, as on Solaris) but may not be overridden */
168 protected final void setBigEndian(boolean bigEndian) {
169 this.bigEndian = bigEndian;
170 }
171
172 /** May be called by subclasses to clear out the cache but may not
173 be overridden. For convenience, this can be called even if the
174 cache has not been initialized. */
175 protected final void clearCache() {
176 if (cache != null) {
177 cache.clear();
178 }
179 }
180
181 /** May be called by subclasses to disable the cache (for example,
182 when the target process has been resumed) but may not be
183 overridden. For convenience, this can be called even if the
184 cache has not been initialized. */
185 protected final void disableCache() {
186 if (cache != null) {
187 cache.disable();
188 }
189 }
190
191 /** May be called by subclasses to re-enable the cache (for example,
192 when the target process has been suspended) but may not be
193 overridden. For convenience, this can be called even if the
194 cache has not been initialized. */
195 protected final void enableCache() {
196 if (cache != null) {
197 cache.enable();
198 }
199 }
200
201 /** May be called by subclasses directly but may not be overridden */
202 protected final byte[] readBytes(long address, long numBytes)
203 throws UnmappedAddressException, DebuggerException {
204 if (cache != null) {
205 return cache.getData(address, numBytes);
206 } else {
207 ReadResult res = readBytesFromProcess(address, numBytes);
208 if (res.getData() != null) {
209 return res.getData();
210 }
211 throw new UnmappedAddressException(res.getFailureAddress());
212 }
213 }
214
215 /** May be called by subclasses directly but may not be overridden */
216 protected final void writeBytes(long address, long numBytes, byte[] data)
217 throws UnmappedAddressException, DebuggerException {
218 if (cache != null) {
219 cache.clear(address, numBytes);
220 }
221 writeBytesToProcess(address, numBytes, data);
222 }
223
224 public boolean readJBoolean(long address)
225 throws UnmappedAddressException, UnalignedAddressException {
226 checkJavaConfigured();
227 utils.checkAlignment(address, jbooleanSize);
228 if (useFastAccessors) {
229 return (cache.getByte(address) != 0);
230 } else {
231 byte[] data = readBytes(address, jbooleanSize);
232 return utils.dataToJBoolean(data, jbooleanSize);
233 }
234 }
235
236 public byte readJByte(long address)
237 throws UnmappedAddressException, UnalignedAddressException {
238 checkJavaConfigured();
239 utils.checkAlignment(address, jbyteSize);
240 if (useFastAccessors) {
241 return cache.getByte(address);
242 } else {
243 byte[] data = readBytes(address, jbyteSize);
244 return utils.dataToJByte(data, jbyteSize);
245 }
246 }
247
248 // NOTE: assumes value does not span pages (may be bad assumption on
249 // Solaris/x86; see unalignedAccessesOkay in DbxDebugger hierarchy)
250 public char readJChar(long address)
251 throws UnmappedAddressException, UnalignedAddressException {
252 checkJavaConfigured();
253 utils.checkAlignment(address, jcharSize);
254 if (useFastAccessors) {
255 return cache.getChar(address, bigEndian);
256 } else {
257 byte[] data = readBytes(address, jcharSize);
258 return (char) utils.dataToJChar(data, jcharSize);
259 }
260 }
261
262 // NOTE: assumes value does not span pages (may be bad assumption on
263 // Solaris/x86; see unalignedAccessesOkay in DbxDebugger hierarchy)
264 public double readJDouble(long address)
265 throws UnmappedAddressException, UnalignedAddressException {
266 checkJavaConfigured();
267 utils.checkAlignment(address, jdoubleSize);
268 if (useFastAccessors) {
269 return cache.getDouble(address, bigEndian);
270 } else {
271 byte[] data = readBytes(address, jdoubleSize);
272 return utils.dataToJDouble(data, jdoubleSize);
273 }
274 }
275
276 // NOTE: assumes value does not span pages (may be bad assumption on
277 // Solaris/x86; see unalignedAccessesOkay in DbxDebugger hierarchy)
278 public float readJFloat(long address)
279 throws UnmappedAddressException, UnalignedAddressException {
280 checkJavaConfigured();
281 utils.checkAlignment(address, jfloatSize);
282 if (useFastAccessors) {
283 return cache.getFloat(address, bigEndian);
284 } else {
285 byte[] data = readBytes(address, jfloatSize);
286 return utils.dataToJFloat(data, jfloatSize);
287 }
288 }
289
290 // NOTE: assumes value does not span pages (may be bad assumption on
291 // Solaris/x86; see unalignedAccessesOkay in DbxDebugger hierarchy)
292 public int readJInt(long address)
293 throws UnmappedAddressException, UnalignedAddressException {
294 checkJavaConfigured();
295 utils.checkAlignment(address, jintSize);
296 if (useFastAccessors) {
297 return cache.getInt(address, bigEndian);
298 } else {
299 byte[] data = readBytes(address, jintSize);
300 return utils.dataToJInt(data, jintSize);
301 }
302 }
303
304 // NOTE: assumes value does not span pages (may be bad assumption on
305 // Solaris/x86; see unalignedAccessesOkay in DbxDebugger hierarchy)
306 public long readJLong(long address)
307 throws UnmappedAddressException, UnalignedAddressException {
308 checkJavaConfigured();
309 utils.checkAlignment(address, jlongSize);
310 if (useFastAccessors) {
311 return cache.getLong(address, bigEndian);
312 } else {
313 byte[] data = readBytes(address, jlongSize);
314 return utils.dataToJLong(data, jlongSize);
315 }
316 }
317
318 // NOTE: assumes value does not span pages (may be bad assumption on
319 // Solaris/x86; see unalignedAccessesOkay in DbxDebugger hierarchy)
320 public short readJShort(long address)
321 throws UnmappedAddressException, UnalignedAddressException {
322 checkJavaConfigured();
323 utils.checkAlignment(address, jshortSize);
324 if (useFastAccessors) {
325 return cache.getShort(address, bigEndian);
326 } else {
327 byte[] data = readBytes(address, jshortSize);
328 return utils.dataToJShort(data, jshortSize);
329 }
330 }
331
332 // NOTE: assumes value does not span pages (may be bad assumption on
333 // Solaris/x86; see unalignedAccessesOkay in DbxDebugger hierarchy)
334 public long readCInteger(long address, long numBytes, boolean isUnsigned)
335 throws UnmappedAddressException, UnalignedAddressException {
336 checkConfigured();
337 utils.checkAlignment(address, numBytes);
338 if (useFastAccessors) {
339 if (isUnsigned) {
340 switch((int) numBytes) {
341 case 1: return cache.getByte(address) & 0xFF;
342 case 2: return cache.getShort(address, bigEndian) & 0xFFFF;
343 case 4: return cache.getInt(address, bigEndian) & 0xFFFFFFFFL;
344 case 8: return cache.getLong(address, bigEndian);
345 default: {
346 byte[] data = readBytes(address, numBytes);
347 return utils.dataToCInteger(data, isUnsigned);
348 }
349 }
350 } else {
351 switch((int) numBytes) {
352 case 1: return cache.getByte(address);
353 case 2: return cache.getShort(address, bigEndian);
354 case 4: return cache.getInt(address, bigEndian);
355 case 8: return cache.getLong(address, bigEndian);
356 default: {
357 byte[] data = readBytes(address, numBytes);
358 return utils.dataToCInteger(data, isUnsigned);
359 }
360 }
361 }
362 } else {
363 byte[] data = readBytes(address, numBytes);
364 return utils.dataToCInteger(data, isUnsigned);
365 }
366 }
367
368 public void writeJBoolean(long address, boolean value)
369 throws UnmappedAddressException, UnalignedAddressException {
370 checkJavaConfigured();
371 utils.checkAlignment(address, jbooleanSize);
372 byte[] data = utils.jbooleanToData(value);
373 writeBytes(address, jbooleanSize, data);
374 }
375
376 public void writeJByte(long address, byte value)
377 throws UnmappedAddressException, UnalignedAddressException {
378 checkJavaConfigured();
379 utils.checkAlignment(address, jbyteSize);
380 byte[] data = utils.jbyteToData(value);
381 writeBytes(address, jbyteSize, data);
382 }
383
384 public void writeJChar(long address, char value)
385 throws UnmappedAddressException, UnalignedAddressException {
386 checkJavaConfigured();
387 utils.checkAlignment(address, jcharSize);
388 byte[] data = utils.jcharToData(value);
389 writeBytes(address, jcharSize, data);
390 }
391
392 public void writeJDouble(long address, double value)
393 throws UnmappedAddressException, UnalignedAddressException {
394 checkJavaConfigured();
395 utils.checkAlignment(address, jdoubleSize);
396 byte[] data = utils.jdoubleToData(value);
397 writeBytes(address, jdoubleSize, data);
398 }
399
400 public void writeJFloat(long address, float value)
401 throws UnmappedAddressException, UnalignedAddressException {
402 checkJavaConfigured();
403 utils.checkAlignment(address, jfloatSize);
404 byte[] data = utils.jfloatToData(value);
405 writeBytes(address, jfloatSize, data);
406 }
407
408 public void writeJInt(long address, int value)
409 throws UnmappedAddressException, UnalignedAddressException {
410 checkJavaConfigured();
411 utils.checkAlignment(address, jintSize);
412 byte[] data = utils.jintToData(value);
413 writeBytes(address, jintSize, data);
414 }
415
416 public void writeJLong(long address, long value)
417 throws UnmappedAddressException, UnalignedAddressException {
418 checkJavaConfigured();
419 utils.checkAlignment(address, jlongSize);
420 byte[] data = utils.jlongToData(value);
421 writeBytes(address, jlongSize, data);
422 }
423
424 public void writeJShort(long address, short value)
425 throws UnmappedAddressException, UnalignedAddressException {
426 checkJavaConfigured();
427 utils.checkAlignment(address, jshortSize);
428 byte[] data = utils.jshortToData(value);
429 writeBytes(address, jshortSize, data);
430 }
431
432 public void writeCInteger(long address, long numBytes, long value)
433 throws UnmappedAddressException, UnalignedAddressException {
434 checkConfigured();
435 utils.checkAlignment(address, numBytes);
436 byte[] data = utils.cIntegerToData(numBytes, value);
437 writeBytes(address, numBytes, data);
438 }
439
440 protected long readAddressValue(long address)
441 throws UnmappedAddressException, UnalignedAddressException {
442 return readCInteger(address, machDesc.getAddressSize(), true);
443 }
444
445 protected void writeAddressValue(long address, long value)
446 throws UnmappedAddressException, UnalignedAddressException {
447 writeCInteger(address, machDesc.getAddressSize(), value);
448 }
449
450 /** Can be called by subclasses but can not be overridden */
451 protected final void checkConfigured() {
452 if (machDesc == null) {
453 throw new RuntimeException("MachineDescription must have been set by this point");
454 }
455 if (utils == null) {
456 throw new RuntimeException("DebuggerUtilities must have been set by this point");
457 }
458 }
459
460 /** Can be called by subclasses but can not be overridden */
461 protected final void checkJavaConfigured() {
462 checkConfigured();
463
464 if (!javaPrimitiveTypesConfigured) {
465 throw new RuntimeException("Java primitive type sizes have not yet been configured");
466 }
467 }
468
469 /** Possibly override page cache size with user-specified property */
470 protected int parseCacheNumPagesProperty(int defaultNum) {
471 String cacheNumPagesString = System.getProperty("cacheNumPages");
472 if (cacheNumPagesString != null) {
473 try {
474 return Integer.parseInt(cacheNumPagesString);
475 } catch (Exception e) {
476 System.err.println("Error parsing cacheNumPages property:");
477 e.printStackTrace();
478 }
479 }
480 return defaultNum;
481 }
482
483 /** Interim solution for allowing subclasses to write bytes to
484 process until we make that functionality available in the basic
485 Address interface */
486 protected void invalidatePageCache(long startAddress, long numBytes) {
487 cache.clear(startAddress, numBytes);
488 }
489
490 public long getJBooleanSize() {
491 return jbooleanSize;
492 }
493
494 public long getJByteSize() {
495 return jbyteSize;
496 }
497
498 public long getJCharSize() {
499 return jcharSize;
500 }
501
502 public long getJDoubleSize() {
503 return jdoubleSize;
504 }
505
506 public long getJFloatSize() {
507 return jfloatSize;
508 }
509
510 public long getJIntSize() {
511 return jintSize;
512 }
513
514 public long getJLongSize() {
515 return jlongSize;
516 }
517
518 public long getJShortSize() {
519 return jshortSize;
520 }
521 }