0
|
1 /*
|
|
2 * Copyright 2000-2003 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 /** A class representing an arbitrary-sized page which can be linked
|
|
28 into a list. Used by the PageCache. */
|
|
29
|
|
30 public class Page {
|
|
31 private long baseAddress;
|
|
32 private byte[] data;
|
|
33 private Page prev;
|
|
34 private Page next;
|
|
35 private long unmappedPageLength;
|
|
36
|
|
37 /** The length of the data[] array implicitly defines the size of the
|
|
38 page. */
|
|
39 public Page(long baseAddress, byte[] data) {
|
|
40 this.baseAddress = baseAddress;
|
|
41 this.data = data;
|
|
42 }
|
|
43
|
|
44 /** This constructor creates an "unmapped" page of the specified
|
|
45 length. Fetches from this page will cause -1 to be inserted into
|
|
46 the destination buffer. */
|
|
47 public Page(long baseAddress, long unmappedPageLength) {
|
|
48 this.baseAddress = baseAddress;
|
|
49 this.unmappedPageLength = unmappedPageLength;
|
|
50 }
|
|
51
|
|
52 public long getBaseAddress() {
|
|
53 return baseAddress;
|
|
54 }
|
|
55
|
|
56 public long getSize() {
|
|
57 if (data != null) {
|
|
58 return data.length;
|
|
59 } else {
|
|
60 return unmappedPageLength;
|
|
61 }
|
|
62 }
|
|
63
|
|
64 /** Indicates whether this page is mapped in the remote process's
|
|
65 address space */
|
|
66 public boolean isMapped() {
|
|
67 return (data != null);
|
|
68 }
|
|
69
|
|
70 public Page getPrev() {
|
|
71 return prev;
|
|
72 }
|
|
73
|
|
74 public void setPrev(Page prev) {
|
|
75 this.prev = prev;
|
|
76 }
|
|
77
|
|
78 public Page getNext() {
|
|
79 return next;
|
|
80 }
|
|
81
|
|
82 public void setNext(Page next) {
|
|
83 this.next = next;
|
|
84 }
|
|
85
|
|
86 /** Throws IndexOutOfBoundsException if the number of bytes
|
|
87 requested is greater than the page size, or if the start address
|
|
88 doesn't fall within the page. There are no guarantees on whether
|
|
89 any data was actually fetched if an IndexOutOfBoundsException is
|
|
90 thrown. If this page is unmapped, -1 is returned for all
|
|
91 addresses on this page. */
|
|
92 public void getData(long startAddress, long numBytes,
|
|
93 int[] destBuf, long destBufOffset)
|
|
94 throws IndexOutOfBoundsException {
|
|
95 int startOffset = (int) (startAddress - baseAddress);
|
|
96 if ((data == null) &&
|
|
97 ((startOffset < 0) || ((startOffset + numBytes) > (baseAddress + unmappedPageLength)))) {
|
|
98 throw new IndexOutOfBoundsException("startAddress = " + startAddress +
|
|
99 ", baseAddress = " + baseAddress +
|
|
100 ", unmappedPageLength = " + unmappedPageLength);
|
|
101 }
|
|
102 for (int i = 0; i < (int) numBytes; ++i) {
|
|
103 if (data != null) {
|
|
104 destBuf[i + (int) destBufOffset] = ((int) (data[i + startOffset]) & 0x000000FF);
|
|
105 } else {
|
|
106 destBuf[i + (int) destBufOffset] = -1;
|
|
107 }
|
|
108 }
|
|
109 }
|
|
110
|
|
111 /** Throws IndexOutOfBoundsException if the number of bytes
|
|
112 requested is greater than the page size, or if the start address
|
|
113 doesn't fall within the page. There are no guarantees on whether
|
|
114 any data was actually fetched if an IndexOutOfBoundsException is
|
|
115 thrown. If this page is unmapped, throws a RuntimeException;
|
|
116 this should be watched for at higher levels. */
|
|
117 public void getDataAsBytes(long startAddress, long numBytes,
|
|
118 byte[] destBuf, long destBufOffset)
|
|
119 throws IndexOutOfBoundsException {
|
|
120 long startOffset = startAddress - baseAddress;
|
|
121 if (data == null) {
|
|
122 throw new RuntimeException("Bug in PageCache; should not fetch from unmapped pages using getDataAsBytes");
|
|
123 }
|
|
124 System.arraycopy(data, (int) startOffset, destBuf, (int) destBufOffset, (int) numBytes);
|
|
125 }
|
|
126
|
|
127 public boolean getBoolean(long address) {
|
|
128 return (getByte(address) != 0);
|
|
129 }
|
|
130
|
|
131 public byte getByte(long address) {
|
|
132 return data[(int) address - (int) baseAddress];
|
|
133 }
|
|
134
|
|
135 public short getShort(long address, boolean bigEndian) {
|
|
136 int start = (int) address - (int) baseAddress;
|
|
137 if (bigEndian) {
|
|
138 return (short)
|
|
139 (((data[start + 1] & 0xFF)) |
|
|
140 ((data[start] & 0xFF) << 8));
|
|
141 } else {
|
|
142 return (short)
|
|
143 (((data[start + 1] & 0xFF) << 8) |
|
|
144 ((data[start] & 0xFF)));
|
|
145 }
|
|
146 }
|
|
147
|
|
148 public char getChar(long address, boolean bigEndian) {
|
|
149 return (char) getShort(address, bigEndian);
|
|
150 }
|
|
151
|
|
152 public int getInt(long address, boolean bigEndian) {
|
|
153 int start = (int) address - (int) baseAddress;
|
|
154 if (bigEndian) {
|
|
155 return
|
|
156 ((data[start + 3] & 0xFF)) |
|
|
157 ((data[start + 2] & 0xFF) << 8) |
|
|
158 ((data[start + 1] & 0xFF) << 16) |
|
|
159 ((data[start] & 0xFF) << 24);
|
|
160 } else {
|
|
161 return
|
|
162 ((data[start + 3] & 0xFF) << 24) |
|
|
163 ((data[start + 2] & 0xFF) << 16) |
|
|
164 ((data[start + 1] & 0xFF) << 8) |
|
|
165 ((data[start] & 0xFF));
|
|
166 }
|
|
167 }
|
|
168
|
|
169 public long getLong(long address, boolean bigEndian) {
|
|
170 int start = (int) address - (int) baseAddress;
|
|
171 if (bigEndian) {
|
|
172 return
|
|
173 ((data[start + 7] & 0xFFL)) |
|
|
174 ((data[start + 6] & 0xFFL) << 8) |
|
|
175 ((data[start + 5] & 0xFFL) << 16) |
|
|
176 ((data[start + 4] & 0xFFL) << 24) |
|
|
177 ((data[start + 3] & 0xFFL) << 32) |
|
|
178 ((data[start + 2] & 0xFFL) << 40) |
|
|
179 ((data[start + 1] & 0xFFL) << 48) |
|
|
180 ((data[start] & 0xFFL) << 56);
|
|
181 } else {
|
|
182 return
|
|
183 ((data[start + 7] & 0xFFL) << 56) |
|
|
184 ((data[start + 6] & 0xFFL) << 48) |
|
|
185 ((data[start + 5] & 0xFFL) << 40) |
|
|
186 ((data[start + 4] & 0xFFL) << 32) |
|
|
187 ((data[start + 3] & 0xFFL) << 24) |
|
|
188 ((data[start + 2] & 0xFFL) << 16) |
|
|
189 ((data[start + 1] & 0xFFL) << 8) |
|
|
190 ((data[start] & 0xFFL));
|
|
191 }
|
|
192 }
|
|
193
|
|
194 public float getFloat(long address, boolean bigEndian) {
|
|
195 return Float.intBitsToFloat(getInt(address, bigEndian));
|
|
196 }
|
|
197
|
|
198 public double getDouble(long address, boolean bigEndian) {
|
|
199 return Double.longBitsToDouble(getLong(address, bigEndian));
|
|
200 }
|
|
201 }
|