Mercurial > hg > truffle
annotate agent/src/share/classes/sun/jvm/hotspot/debugger/win32/coff/COFFFileParser.java @ 20456:64156d22e49d
8032247: SA: Constantpool lookup for invokedynamic is not implemented
Summary: implement constant pool lookup for invokedynamic
Reviewed-by: sla, sspitsyn
author | dsamersoff |
---|---|
date | Thu, 11 Sep 2014 11:55:30 -0700 |
parents | d6cd0d55d0b5 |
children |
rev | line source |
---|---|
0 | 1 /* |
2072
d6cd0d55d0b5
6987812: 2/3 SAJDI: "gHotSpotVMTypes was not initialized properly in the remote process"
dcubed
parents:
1552
diff
changeset
|
2 * Copyright (c) 2000, 2010, 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:
0
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
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:
0
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
25 package sun.jvm.hotspot.debugger.win32.coff; | |
26 | |
27 import java.io.*; | |
28 import java.nio.*; | |
29 import java.nio.channels.*; | |
30 import java.util.*; | |
31 | |
32 import sun.jvm.hotspot.utilities.memo.*; | |
33 import sun.jvm.hotspot.utilities.Assert; | |
34 import sun.jvm.hotspot.debugger.DataSource; | |
35 import sun.jvm.hotspot.debugger.MappedByteBufferDataSource; | |
36 | |
37 /** Top-level factory which parses COFF files, including object files, | |
38 Portable Executables and DLLs. Returns {@link | |
39 sun.jvm.hotspot.debugger.win32.coff.COFFFile} objects. This class is a | |
40 singleton. */ | |
41 | |
42 public class COFFFileParser { | |
43 private static COFFFileParser soleInstance; | |
44 | |
45 // Constants from the file format documentation | |
46 private static final int COFF_HEADER_SIZE = 20; | |
47 private static final int SECTION_HEADER_SIZE = 40; | |
48 private static final int SYMBOL_SIZE = 18; | |
49 private static final int RELOCATION_SIZE = 10; | |
50 private static final int LINE_NUMBER_SIZE = 6; | |
51 | |
52 private static final String US_ASCII = "US-ASCII"; | |
53 | |
54 private COFFFileParser() {} | |
55 | |
56 /** This class is a singleton; returns the sole instance. */ | |
57 public static COFFFileParser getParser() { | |
58 if (soleInstance == null) { | |
59 soleInstance = new COFFFileParser(); | |
60 } | |
61 return soleInstance; | |
62 } | |
63 | |
64 public COFFFile parse(String filename) throws COFFException { | |
65 try { | |
66 File file = new File(filename); | |
67 FileInputStream stream = new FileInputStream(file); | |
68 MappedByteBuffer buf = stream.getChannel().map(FileChannel.MapMode.READ_ONLY, | |
69 0, | |
70 file.length()); | |
71 | |
72 // This is pretty confusing. The file format is little-endian | |
73 // and so is the CPU. In order for the multi-byte accessors to | |
74 // work properly we must NOT change the endianness of the | |
75 // MappedByteBuffer. Need to think about this some more and file | |
76 // a bug if there is one. (FIXME) | |
77 // buf.order(ByteOrder.nativeOrder()); | |
78 return parse(new MappedByteBufferDataSource(buf)); | |
79 } catch (FileNotFoundException e) { | |
80 throw new COFFException(e); | |
81 } catch (IOException e) { | |
82 throw new COFFException(e); | |
83 } | |
84 } | |
85 | |
86 public COFFFile parse(DataSource source) throws COFFException { | |
87 return new COFFFileImpl(source); | |
88 } | |
89 | |
90 class COFFFileImpl implements COFFFile { | |
91 private DataSource file; | |
92 private long filePos; | |
93 private boolean isImage; | |
94 private long imageHeaderOffset; | |
95 private MemoizedObject header = new MemoizedObject() { | |
96 public Object computeValue() { | |
97 return new COFFHeaderImpl(); | |
98 } | |
99 }; | |
100 | |
101 COFFFileImpl(DataSource file) throws COFFException { | |
102 this.file = file; | |
103 initialize(); | |
104 } | |
105 | |
106 public boolean isImage() { | |
107 return isImage; | |
108 } | |
109 | |
110 public COFFHeader getHeader() { | |
111 return (COFFHeaderImpl) header.getValue(); | |
112 } | |
113 | |
114 class COFFHeaderImpl implements COFFHeader { | |
115 private short machine; | |
116 private short numberOfSections; | |
117 private int timeDateStamp; | |
118 private int pointerToSymbolTable; | |
119 private int numberOfSymbols; | |
120 private short sizeOfOptionalHeader; | |
121 private short characteristics; | |
122 private MemoizedObject[] sectionHeaders; | |
123 private MemoizedObject[] symbols; | |
124 | |
2072
d6cd0d55d0b5
6987812: 2/3 SAJDI: "gHotSpotVMTypes was not initialized properly in the remote process"
dcubed
parents:
1552
diff
changeset
|
125 // Init stringTable at decl time since other fields init'ed in the |
d6cd0d55d0b5
6987812: 2/3 SAJDI: "gHotSpotVMTypes was not initialized properly in the remote process"
dcubed
parents:
1552
diff
changeset
|
126 // constructor need the String Table. |
0 | 127 private MemoizedObject stringTable = new MemoizedObject() { |
128 public Object computeValue() { | |
2072
d6cd0d55d0b5
6987812: 2/3 SAJDI: "gHotSpotVMTypes was not initialized properly in the remote process"
dcubed
parents:
1552
diff
changeset
|
129 // the String Table follows the Symbol Table |
0 | 130 int ptr = getPointerToSymbolTable(); |
131 if (ptr == 0) { | |
2072
d6cd0d55d0b5
6987812: 2/3 SAJDI: "gHotSpotVMTypes was not initialized properly in the remote process"
dcubed
parents:
1552
diff
changeset
|
132 // no Symbol Table so no String Table |
0 | 133 return new StringTable(0); |
134 } else { | |
135 return new StringTable(ptr + SYMBOL_SIZE * getNumberOfSymbols()); | |
136 } | |
137 } | |
138 }; | |
139 | |
140 COFFHeaderImpl() { | |
141 seek(imageHeaderOffset); | |
142 machine = readShort(); | |
143 numberOfSections = readShort(); | |
144 timeDateStamp = readInt(); | |
145 pointerToSymbolTable = readInt(); | |
146 numberOfSymbols = readInt(); | |
2072
d6cd0d55d0b5
6987812: 2/3 SAJDI: "gHotSpotVMTypes was not initialized properly in the remote process"
dcubed
parents:
1552
diff
changeset
|
147 // String Table can be accessed at this point because |
d6cd0d55d0b5
6987812: 2/3 SAJDI: "gHotSpotVMTypes was not initialized properly in the remote process"
dcubed
parents:
1552
diff
changeset
|
148 // pointerToSymbolTable and numberOfSymbols fields are set. |
0 | 149 sizeOfOptionalHeader = readShort(); |
150 characteristics = readShort(); | |
151 | |
152 // Set up section headers | |
153 sectionHeaders = new MemoizedObject[numberOfSections]; | |
154 for (int i = 0; i < numberOfSections; i++) { | |
155 final int secHdrOffset = (int) | |
156 (imageHeaderOffset + COFF_HEADER_SIZE + sizeOfOptionalHeader + i * SECTION_HEADER_SIZE); | |
157 sectionHeaders[i] = new MemoizedObject() { | |
158 public Object computeValue() { | |
159 return new SectionHeaderImpl(secHdrOffset); | |
160 } | |
161 }; | |
162 } | |
163 | |
164 // Set up symbols | |
165 symbols = new MemoizedObject[numberOfSymbols]; | |
166 for (int i = 0; i < numberOfSymbols; i++) { | |
167 final int symbolOffset = pointerToSymbolTable + i * SYMBOL_SIZE; | |
168 symbols[i] = new MemoizedObject() { | |
169 public Object computeValue() { | |
170 return new COFFSymbolImpl(symbolOffset); | |
171 } | |
172 }; | |
173 } | |
174 } | |
175 | |
176 public short getMachineType() { return machine; } | |
177 public short getNumberOfSections() { return numberOfSections; } | |
178 public int getTimeDateStamp() { return timeDateStamp; } | |
179 public int getPointerToSymbolTable() { return pointerToSymbolTable; } | |
180 public int getNumberOfSymbols() { return numberOfSymbols; } | |
181 public short getSizeOfOptionalHeader() { return sizeOfOptionalHeader; } | |
182 public OptionalHeader getOptionalHeader() throws COFFException { | |
183 if (getSizeOfOptionalHeader() == 0) { | |
184 return null; | |
185 } | |
186 return new OptionalHeaderImpl((int) (imageHeaderOffset + COFF_HEADER_SIZE)); | |
187 } | |
188 public short getCharacteristics() { return characteristics; } | |
189 public boolean hasCharacteristic(short characteristic) { | |
190 return ((characteristics & characteristic) != 0); | |
191 } | |
192 public SectionHeader getSectionHeader(int index) { | |
193 // NOTE zero-basing of index | |
194 return (SectionHeader) sectionHeaders[index - 1].getValue(); | |
195 } | |
196 public COFFSymbol getCOFFSymbol(int index) { | |
197 return (COFFSymbol) symbols[index].getValue(); | |
198 } | |
199 public int getNumberOfStrings() { | |
200 return getStringTable().getNum(); | |
201 } | |
202 public String getString(int i) { | |
203 return getStringTable().get(i); | |
204 } | |
205 | |
206 StringTable getStringTable() { return (StringTable) stringTable.getValue(); } | |
207 | |
208 // NOTE: can destroy current seek() position! | |
209 int rvaToFileOffset(int rva) { | |
210 if (rva == 0) return 0; | |
211 // Search for section containing RVA | |
212 for (int i = 1; i <= getNumberOfSections(); i++) { | |
213 SectionHeader sec = getSectionHeader(i); | |
214 int va = sec.getVirtualAddress(); | |
215 int sz = sec.getSize(); | |
216 if ((va <= rva) && (rva < (va + sz))) { | |
217 return sec.getPointerToRawData() + (rva - va); | |
218 } | |
219 } | |
220 throw new COFFException("Unable to find RVA 0x" + | |
221 Integer.toHexString(rva) + | |
222 " in any section"); | |
223 } | |
224 | |
225 class OptionalHeaderImpl implements OptionalHeader { | |
226 private short magic; | |
227 private MemoizedObject standardFields; | |
228 private MemoizedObject windowsSpecificFields; | |
229 private MemoizedObject dataDirectories; | |
230 | |
2072
d6cd0d55d0b5
6987812: 2/3 SAJDI: "gHotSpotVMTypes was not initialized properly in the remote process"
dcubed
parents:
1552
diff
changeset
|
231 // We use an offset of 2 because OptionalHeaderStandardFieldsImpl doesn't |
d6cd0d55d0b5
6987812: 2/3 SAJDI: "gHotSpotVMTypes was not initialized properly in the remote process"
dcubed
parents:
1552
diff
changeset
|
232 // include the 'magic' field. |
0 | 233 private static final int STANDARD_FIELDS_OFFSET = 2; |
234 private static final int PE32_WINDOWS_SPECIFIC_FIELDS_OFFSET = 28; | |
235 private static final int PE32_DATA_DIRECTORIES_OFFSET = 96; | |
236 private static final int PE32_PLUS_WINDOWS_SPECIFIC_FIELDS_OFFSET = 24; | |
237 private static final int PE32_PLUS_DATA_DIRECTORIES_OFFSET = 112; | |
238 | |
239 OptionalHeaderImpl(final int offset) { | |
240 seek(offset); | |
241 magic = readShort(); | |
242 | |
243 final boolean isPE32Plus = (magic == MAGIC_PE32_PLUS); | |
244 final int standardFieldsOffset = offset + STANDARD_FIELDS_OFFSET; | |
245 final int windowsSpecificFieldsOffset = offset + | |
246 (isPE32Plus | |
247 ? PE32_PLUS_WINDOWS_SPECIFIC_FIELDS_OFFSET | |
248 : PE32_WINDOWS_SPECIFIC_FIELDS_OFFSET); | |
249 final int dataDirectoriesOffset = offset + | |
250 (isPE32Plus | |
251 ? PE32_PLUS_DATA_DIRECTORIES_OFFSET | |
252 : PE32_DATA_DIRECTORIES_OFFSET); | |
253 | |
254 standardFields = new MemoizedObject() { | |
255 public Object computeValue() { | |
256 return new OptionalHeaderStandardFieldsImpl(standardFieldsOffset, | |
257 isPE32Plus); | |
258 } | |
259 }; | |
260 windowsSpecificFields = new MemoizedObject() { | |
261 public Object computeValue() { | |
262 return new OptionalHeaderWindowsSpecificFieldsImpl(windowsSpecificFieldsOffset, | |
263 isPE32Plus); | |
264 } | |
265 }; | |
266 dataDirectories = new MemoizedObject() { | |
267 public Object computeValue() { | |
268 return new OptionalHeaderDataDirectoriesImpl(dataDirectoriesOffset, | |
269 getWindowsSpecificFields().getNumberOfRvaAndSizes()); | |
270 } | |
271 }; | |
272 } | |
273 | |
274 public short getMagicNumber() { | |
275 return magic; | |
276 } | |
277 | |
278 public OptionalHeaderStandardFields getStandardFields() { | |
279 return (OptionalHeaderStandardFields) standardFields.getValue(); | |
280 } | |
281 | |
282 public OptionalHeaderWindowsSpecificFields getWindowsSpecificFields() { | |
283 return (OptionalHeaderWindowsSpecificFields) windowsSpecificFields.getValue(); | |
284 } | |
285 public OptionalHeaderDataDirectories getDataDirectories() { | |
286 return (OptionalHeaderDataDirectories) dataDirectories.getValue(); | |
287 } | |
288 } | |
289 | |
290 class OptionalHeaderStandardFieldsImpl implements OptionalHeaderStandardFields { | |
291 private boolean isPE32Plus; | |
292 private byte majorLinkerVersion; | |
293 private byte minorLinkerVersion; | |
294 private int sizeOfCode; | |
295 private int sizeOfInitializedData; | |
296 private int sizeOfUninitializedData; | |
297 private int addressOfEntryPoint; | |
298 private int baseOfCode; | |
2072
d6cd0d55d0b5
6987812: 2/3 SAJDI: "gHotSpotVMTypes was not initialized properly in the remote process"
dcubed
parents:
1552
diff
changeset
|
299 private int baseOfData; // only set in PE32 |
0 | 300 |
301 OptionalHeaderStandardFieldsImpl(int offset, | |
302 boolean isPE32Plus) { | |
303 this.isPE32Plus = isPE32Plus; | |
304 seek(offset); | |
305 majorLinkerVersion = readByte(); | |
306 minorLinkerVersion = readByte(); | |
307 sizeOfCode = readInt(); | |
308 sizeOfInitializedData = readInt(); | |
309 sizeOfUninitializedData = readInt(); | |
310 addressOfEntryPoint = readInt(); | |
311 baseOfCode = readInt(); | |
2072
d6cd0d55d0b5
6987812: 2/3 SAJDI: "gHotSpotVMTypes was not initialized properly in the remote process"
dcubed
parents:
1552
diff
changeset
|
312 if (!isPE32Plus) { |
d6cd0d55d0b5
6987812: 2/3 SAJDI: "gHotSpotVMTypes was not initialized properly in the remote process"
dcubed
parents:
1552
diff
changeset
|
313 // only available in PE32 |
0 | 314 baseOfData = readInt(); |
315 } | |
316 } | |
317 | |
318 public byte getMajorLinkerVersion() { return majorLinkerVersion; } | |
319 public byte getMinorLinkerVersion() { return minorLinkerVersion; } | |
320 public int getSizeOfCode() { return sizeOfCode; } | |
321 public int getSizeOfInitializedData() { return sizeOfInitializedData; } | |
322 public int getSizeOfUninitializedData() { return sizeOfUninitializedData; } | |
323 public int getAddressOfEntryPoint() { return addressOfEntryPoint; } | |
324 public int getBaseOfCode() { return baseOfCode; } | |
325 public int getBaseOfData() throws COFFException { | |
326 if (isPE32Plus) { | |
327 throw new COFFException("Not present in PE32+ files"); | |
328 } | |
329 return baseOfData; | |
330 } | |
331 } | |
332 | |
333 class OptionalHeaderWindowsSpecificFieldsImpl implements OptionalHeaderWindowsSpecificFields { | |
334 private long imageBase; | |
335 private int sectionAlignment; | |
336 private int fileAlignment; | |
337 private short majorOperatingSystemVersion; | |
338 private short minorOperatingSystemVersion; | |
339 private short majorImageVersion; | |
340 private short minorImageVersion; | |
341 private short majorSubsystemVersion; | |
342 private short minorSubsystemVersion; | |
343 private int sizeOfImage; | |
344 private int sizeOfHeaders; | |
345 private int checkSum; | |
346 private short subsystem; | |
347 private short dllCharacteristics; | |
348 private long sizeOfStackReserve; | |
349 private long sizeOfStackCommit; | |
350 private long sizeOfHeapReserve; | |
351 private long sizeOfHeapCommit; | |
352 private int loaderFlags; | |
353 private int numberOfRvaAndSizes; | |
354 | |
355 OptionalHeaderWindowsSpecificFieldsImpl(int offset, boolean isPE32Plus) { | |
356 seek(offset); | |
357 | |
358 if (!isPE32Plus) { | |
359 imageBase = maskInt(readInt()); | |
360 } else { | |
361 imageBase = readLong(); | |
362 } | |
363 sectionAlignment = readInt(); | |
364 fileAlignment = readInt(); | |
365 majorOperatingSystemVersion = readShort(); | |
366 minorOperatingSystemVersion = readShort(); | |
367 majorImageVersion = readShort(); | |
368 minorImageVersion = readShort(); | |
369 majorSubsystemVersion = readShort(); | |
370 minorSubsystemVersion = readShort(); | |
371 readInt(); // Reserved | |
372 sizeOfImage = readInt(); | |
373 sizeOfHeaders = readInt(); | |
374 checkSum = readInt(); | |
375 subsystem = readShort(); | |
376 dllCharacteristics = readShort(); | |
377 if (!isPE32Plus) { | |
378 sizeOfStackReserve = maskInt(readInt()); | |
379 sizeOfStackCommit = maskInt(readInt()); | |
380 sizeOfHeapReserve = maskInt(readInt()); | |
381 sizeOfHeapCommit = maskInt(readInt()); | |
382 } else { | |
383 sizeOfStackReserve = readLong(); | |
384 sizeOfStackCommit = readLong(); | |
385 sizeOfHeapReserve = readLong(); | |
386 sizeOfHeapCommit = readLong(); | |
387 } | |
388 loaderFlags = readInt(); | |
389 numberOfRvaAndSizes = readInt(); | |
390 } | |
391 | |
392 public long getImageBase() { return imageBase; } | |
393 public int getSectionAlignment() { return sectionAlignment; } | |
394 public int getFileAlignment() { return fileAlignment; } | |
395 public short getMajorOperatingSystemVersion() { return majorOperatingSystemVersion; } | |
396 public short getMinorOperatingSystemVersion() { return minorOperatingSystemVersion; } | |
397 public short getMajorImageVersion() { return majorImageVersion; } | |
398 public short getMinorImageVersion() { return minorImageVersion; } | |
399 public short getMajorSubsystemVersion() { return majorSubsystemVersion; } | |
400 public short getMinorSubsystemVersion() { return minorSubsystemVersion; } | |
401 public int getSizeOfImage() { return sizeOfImage; } | |
402 public int getSizeOfHeaders() { return sizeOfHeaders; } | |
403 public int getCheckSum() { return checkSum; } | |
404 public short getSubsystem() { return subsystem; } | |
405 public short getDLLCharacteristics() { return dllCharacteristics; } | |
406 public long getSizeOfStackReserve() { return sizeOfStackReserve; } | |
407 public long getSizeOfStackCommit() { return sizeOfStackCommit; } | |
408 public long getSizeOfHeapReserve() { return sizeOfHeapReserve; } | |
409 public long getSizeOfHeapCommit() { return sizeOfHeapCommit; } | |
410 public int getLoaderFlags() { return loaderFlags; } | |
411 public int getNumberOfRvaAndSizes() { return numberOfRvaAndSizes; } | |
412 | |
413 private long maskInt(long arg) { | |
414 return (arg & 0x00000000FFFFFFFFL); | |
415 } | |
416 } | |
417 | |
418 class OptionalHeaderDataDirectoriesImpl implements OptionalHeaderDataDirectories { | |
419 private int numberOfRvaAndSizes; | |
420 private MemoizedObject[] dataDirectories; | |
421 private MemoizedObject exportDirectoryTable; | |
422 private MemoizedObject debugDirectory; | |
423 | |
424 private static final int DATA_DIRECTORY_SIZE = 8; | |
425 | |
426 OptionalHeaderDataDirectoriesImpl(int offset, | |
427 int numberOfRvaAndSizes) { | |
428 this.numberOfRvaAndSizes = numberOfRvaAndSizes; | |
429 dataDirectories = new MemoizedObject[numberOfRvaAndSizes]; | |
430 for (int i = 0; i < numberOfRvaAndSizes; i++) { | |
431 final int dirOffset = offset + (i * DATA_DIRECTORY_SIZE); | |
432 dataDirectories[i] = new MemoizedObject() { | |
433 public Object computeValue() { | |
434 return new DataDirectoryImpl(dirOffset); | |
435 } | |
436 }; | |
437 } | |
438 | |
439 exportDirectoryTable = new MemoizedObject() { | |
440 public Object computeValue() { | |
441 DataDirectory dir = getExportTable(); | |
442 if (dir.getRVA() == 0 || dir.getSize() == 0) { | |
443 return null; | |
444 } | |
2072
d6cd0d55d0b5
6987812: 2/3 SAJDI: "gHotSpotVMTypes was not initialized properly in the remote process"
dcubed
parents:
1552
diff
changeset
|
445 // ExportDirectoryTableImpl needs both the RVA and the |
d6cd0d55d0b5
6987812: 2/3 SAJDI: "gHotSpotVMTypes was not initialized properly in the remote process"
dcubed
parents:
1552
diff
changeset
|
446 // RVA converted to a file offset. |
d6cd0d55d0b5
6987812: 2/3 SAJDI: "gHotSpotVMTypes was not initialized properly in the remote process"
dcubed
parents:
1552
diff
changeset
|
447 return new |
d6cd0d55d0b5
6987812: 2/3 SAJDI: "gHotSpotVMTypes was not initialized properly in the remote process"
dcubed
parents:
1552
diff
changeset
|
448 ExportDirectoryTableImpl(dir.getRVA(), dir.getSize()); |
0 | 449 } |
450 }; | |
451 | |
452 debugDirectory = new MemoizedObject() { | |
453 public Object computeValue() { | |
454 DataDirectory dir = getDebug(); | |
455 if (dir.getRVA() == 0 || dir.getSize() == 0) { | |
456 return null; | |
457 } | |
458 return new DebugDirectoryImpl(rvaToFileOffset(dir.getRVA()), dir.getSize()); | |
459 } | |
460 }; | |
461 } | |
462 | |
463 public DataDirectory getExportTable() throws COFFException { | |
464 return (DataDirectory) dataDirectories[checkIndex(0)].getValue(); | |
465 } | |
466 public DataDirectory getImportTable() throws COFFException { | |
467 return (DataDirectory) dataDirectories[checkIndex(1)].getValue(); | |
468 } | |
469 public DataDirectory getResourceTable() throws COFFException { | |
470 return (DataDirectory) dataDirectories[checkIndex(2)].getValue(); | |
471 } | |
472 public DataDirectory getExceptionTable() throws COFFException { | |
473 return (DataDirectory) dataDirectories[checkIndex(3)].getValue(); | |
474 } | |
475 public DataDirectory getCertificateTable() throws COFFException { | |
476 return (DataDirectory) dataDirectories[checkIndex(4)].getValue(); | |
477 } | |
478 public DataDirectory getBaseRelocationTable() throws COFFException { | |
479 return (DataDirectory) dataDirectories[checkIndex(5)].getValue(); | |
480 } | |
481 public DataDirectory getDebug() throws COFFException { | |
482 return (DataDirectory) dataDirectories[checkIndex(6)].getValue(); | |
483 } | |
484 public DataDirectory getArchitecture() throws COFFException { | |
485 return (DataDirectory) dataDirectories[checkIndex(7)].getValue(); | |
486 } | |
487 public DataDirectory getGlobalPtr() throws COFFException { | |
488 return (DataDirectory) dataDirectories[checkIndex(8)].getValue(); | |
489 } | |
490 public DataDirectory getTLSTable() throws COFFException { | |
491 return (DataDirectory) dataDirectories[checkIndex(9)].getValue(); | |
492 } | |
493 public DataDirectory getLoadConfigTable() throws COFFException { | |
494 return (DataDirectory) dataDirectories[checkIndex(10)].getValue(); | |
495 } | |
496 public DataDirectory getBoundImportTable() throws COFFException { | |
497 return (DataDirectory) dataDirectories[checkIndex(11)].getValue(); | |
498 } | |
499 public DataDirectory getImportAddressTable() throws COFFException { | |
500 return (DataDirectory) dataDirectories[checkIndex(12)].getValue(); | |
501 } | |
502 public DataDirectory getDelayImportDescriptor() throws COFFException { | |
503 return (DataDirectory) dataDirectories[checkIndex(13)].getValue(); | |
504 } | |
505 public DataDirectory getCOMPlusRuntimeHeader() throws COFFException { | |
506 return (DataDirectory) dataDirectories[checkIndex(14)].getValue(); | |
507 } | |
508 | |
509 public ExportDirectoryTable getExportDirectoryTable() throws COFFException { | |
510 return (ExportDirectoryTable) exportDirectoryTable.getValue(); | |
511 } | |
512 | |
513 public DebugDirectory getDebugDirectory() throws COFFException { | |
514 return (DebugDirectory) debugDirectory.getValue(); | |
515 } | |
516 | |
517 private int checkIndex(int index) throws COFFException { | |
518 if ((index < 0) || (index >= dataDirectories.length)) { | |
519 throw new COFFException("Directory " + index + " unavailable (only " + | |
520 numberOfRvaAndSizes + " tables present)"); | |
521 } | |
522 return index; | |
523 } | |
524 } | |
525 | |
526 class DataDirectoryImpl implements DataDirectory { | |
527 int rva; | |
528 int size; | |
529 | |
530 DataDirectoryImpl(int offset) { | |
531 seek(offset); | |
532 rva = readInt(); | |
533 size = readInt(); | |
534 } | |
535 | |
536 public int getRVA() { return rva; } | |
537 public int getSize() { return size; } | |
538 } | |
539 | |
540 class ExportDirectoryTableImpl implements ExportDirectoryTable { | |
2072
d6cd0d55d0b5
6987812: 2/3 SAJDI: "gHotSpotVMTypes was not initialized properly in the remote process"
dcubed
parents:
1552
diff
changeset
|
541 private int exportDataDirRVA; |
0 | 542 private int offset; |
543 private int size; | |
544 | |
545 private int exportFlags; | |
546 private int timeDateStamp; | |
547 private short majorVersion; | |
548 private short minorVersion; | |
549 private int nameRVA; | |
550 private int ordinalBase; | |
551 private int addressTableEntries; | |
552 private int numberOfNamePointers; | |
553 private int exportAddressTableRVA; | |
554 private int namePointerTableRVA; | |
555 private int ordinalTableRVA; | |
556 | |
557 private MemoizedObject dllName; | |
558 | |
559 private MemoizedObject exportNameTable; | |
560 private MemoizedObject exportNamePointerTable; | |
561 private MemoizedObject exportOrdinalTable; | |
562 private MemoizedObject exportAddressTable; | |
563 | |
2072
d6cd0d55d0b5
6987812: 2/3 SAJDI: "gHotSpotVMTypes was not initialized properly in the remote process"
dcubed
parents:
1552
diff
changeset
|
564 ExportDirectoryTableImpl(int exportDataDirRVA, int size) { |
d6cd0d55d0b5
6987812: 2/3 SAJDI: "gHotSpotVMTypes was not initialized properly in the remote process"
dcubed
parents:
1552
diff
changeset
|
565 this.exportDataDirRVA = exportDataDirRVA; |
d6cd0d55d0b5
6987812: 2/3 SAJDI: "gHotSpotVMTypes was not initialized properly in the remote process"
dcubed
parents:
1552
diff
changeset
|
566 offset = rvaToFileOffset(exportDataDirRVA); |
0 | 567 this.size = size; |
568 seek(offset); | |
569 exportFlags = readInt(); | |
570 timeDateStamp = readInt(); | |
571 majorVersion = readShort(); | |
572 minorVersion = readShort(); | |
573 nameRVA = readInt(); | |
574 ordinalBase = readInt(); | |
575 addressTableEntries = readInt(); | |
576 numberOfNamePointers = readInt(); | |
577 exportAddressTableRVA = readInt(); | |
578 namePointerTableRVA = readInt(); | |
579 ordinalTableRVA = readInt(); | |
580 | |
581 dllName = new MemoizedObject() { | |
582 public Object computeValue() { | |
583 seek(rvaToFileOffset(getNameRVA())); | |
584 return readCString(); | |
585 } | |
586 }; | |
587 | |
588 exportNamePointerTable = new MemoizedObject() { | |
589 public Object computeValue() { | |
590 int[] pointers = new int[getNumberOfNamePointers()]; | |
591 seek(rvaToFileOffset(getNamePointerTableRVA())); | |
592 // Must make two passes to avoid rvaToFileOffset | |
593 // destroying seek() position | |
594 for (int i = 0; i < pointers.length; i++) { | |
595 pointers[i] = readInt(); | |
596 } | |
597 for (int i = 0; i < pointers.length; i++) { | |
598 pointers[i] = rvaToFileOffset(pointers[i]); | |
599 } | |
600 return pointers; | |
601 } | |
602 }; | |
603 | |
604 exportNameTable = new MemoizedObject() { | |
605 public Object computeValue() { | |
606 return new ExportNameTable(getExportNamePointerTable()); | |
607 } | |
608 }; | |
609 | |
610 exportOrdinalTable = new MemoizedObject() { | |
611 public Object computeValue() { | |
2072
d6cd0d55d0b5
6987812: 2/3 SAJDI: "gHotSpotVMTypes was not initialized properly in the remote process"
dcubed
parents:
1552
diff
changeset
|
612 // number of ordinals is same as the number of name pointers |
0 | 613 short[] ordinals = new short[getNumberOfNamePointers()]; |
614 seek(rvaToFileOffset(getOrdinalTableRVA())); | |
615 for (int i = 0; i < ordinals.length; i++) { | |
616 ordinals[i] = readShort(); | |
617 } | |
618 return ordinals; | |
619 } | |
620 }; | |
621 | |
622 exportAddressTable = new MemoizedObject() { | |
623 public Object computeValue() { | |
624 int[] addresses = new int[getNumberOfAddressTableEntries()]; | |
625 seek(rvaToFileOffset(getExportAddressTableRVA())); | |
2072
d6cd0d55d0b5
6987812: 2/3 SAJDI: "gHotSpotVMTypes was not initialized properly in the remote process"
dcubed
parents:
1552
diff
changeset
|
626 // The Export Address Table values are a union of two |
d6cd0d55d0b5
6987812: 2/3 SAJDI: "gHotSpotVMTypes was not initialized properly in the remote process"
dcubed
parents:
1552
diff
changeset
|
627 // possible values: |
d6cd0d55d0b5
6987812: 2/3 SAJDI: "gHotSpotVMTypes was not initialized properly in the remote process"
dcubed
parents:
1552
diff
changeset
|
628 // Export RVA - The address of the exported symbol when |
d6cd0d55d0b5
6987812: 2/3 SAJDI: "gHotSpotVMTypes was not initialized properly in the remote process"
dcubed
parents:
1552
diff
changeset
|
629 // loaded into memory, relative to the image base. |
d6cd0d55d0b5
6987812: 2/3 SAJDI: "gHotSpotVMTypes was not initialized properly in the remote process"
dcubed
parents:
1552
diff
changeset
|
630 // This value doesn't get converted into a file offset. |
d6cd0d55d0b5
6987812: 2/3 SAJDI: "gHotSpotVMTypes was not initialized properly in the remote process"
dcubed
parents:
1552
diff
changeset
|
631 // Forwarder RVA - The pointer to a null-terminated ASCII |
d6cd0d55d0b5
6987812: 2/3 SAJDI: "gHotSpotVMTypes was not initialized properly in the remote process"
dcubed
parents:
1552
diff
changeset
|
632 // string in the export section. This value gets |
d6cd0d55d0b5
6987812: 2/3 SAJDI: "gHotSpotVMTypes was not initialized properly in the remote process"
dcubed
parents:
1552
diff
changeset
|
633 // converted into a file offset because we have to |
d6cd0d55d0b5
6987812: 2/3 SAJDI: "gHotSpotVMTypes was not initialized properly in the remote process"
dcubed
parents:
1552
diff
changeset
|
634 // fetch the string. |
0 | 635 for (int i = 0; i < addresses.length; i++) { |
636 addresses[i] = readInt(); | |
637 } | |
638 return addresses; | |
639 } | |
640 }; | |
641 } | |
642 | |
643 public int getExportFlags() { return exportFlags; } | |
644 public int getTimeDateStamp() { return timeDateStamp; } | |
645 public short getMajorVersion() { return majorVersion; } | |
646 public short getMinorVersion() { return minorVersion; } | |
647 public int getNameRVA() { return nameRVA; } | |
648 | |
649 public String getDLLName() { | |
650 return (String) dllName.getValue(); | |
651 } | |
652 | |
653 public int getOrdinalBase() { return ordinalBase; } | |
654 public int getNumberOfAddressTableEntries() { return addressTableEntries; } | |
655 public int getNumberOfNamePointers() { return numberOfNamePointers; } | |
656 public int getExportAddressTableRVA() { return exportAddressTableRVA; } | |
657 public int getNamePointerTableRVA() { return namePointerTableRVA; } | |
658 public int getOrdinalTableRVA() { return ordinalTableRVA; } | |
659 | |
660 public String getExportName(int i) { | |
661 return getExportNameTable().get(i); | |
662 } | |
663 | |
664 public short getExportOrdinal(int i) { | |
665 return getExportOrdinalTable()[i]; | |
666 } | |
667 | |
668 public boolean isExportAddressForwarder(short ordinal) { | |
669 int addr = getExportAddress(ordinal); | |
2072
d6cd0d55d0b5
6987812: 2/3 SAJDI: "gHotSpotVMTypes was not initialized properly in the remote process"
dcubed
parents:
1552
diff
changeset
|
670 return ((exportDataDirRVA <= addr) && |
d6cd0d55d0b5
6987812: 2/3 SAJDI: "gHotSpotVMTypes was not initialized properly in the remote process"
dcubed
parents:
1552
diff
changeset
|
671 (addr < (exportDataDirRVA + size))); |
0 | 672 } |
673 | |
674 public String getExportAddressForwarder(short ordinal) { | |
2072
d6cd0d55d0b5
6987812: 2/3 SAJDI: "gHotSpotVMTypes was not initialized properly in the remote process"
dcubed
parents:
1552
diff
changeset
|
675 seek(rvaToFileOffset(getExportAddress(ordinal))); |
0 | 676 return readCString(); |
677 } | |
678 | |
679 public int getExportAddress(short ordinal) { | |
680 | |
681 /////////////////////// | |
682 // FIXME: MAJOR HACK // | |
683 /////////////////////// | |
684 | |
685 // According to the documentation, the first line here is | |
686 // correct. However, it doesn't seem to work. The second | |
687 // one, however, does. | |
688 | |
689 // OK, it's probably due to using negative indices in the | |
690 // export address table in "real life"...need to rethink | |
691 // this when I'm more awake | |
692 | |
693 // return getExportAddressTable()[ordinal - ordinalBase]; | |
694 return getExportAddressTable()[ordinal]; | |
695 } | |
696 | |
697 private ExportNameTable getExportNameTable() { | |
698 return (ExportNameTable) exportNameTable.getValue(); | |
699 } | |
700 | |
701 private int[] getExportNamePointerTable() { | |
702 return (int[]) exportNamePointerTable.getValue(); | |
703 } | |
704 | |
705 private short[] getExportOrdinalTable() { | |
706 return (short[]) exportOrdinalTable.getValue(); | |
707 } | |
708 | |
709 private int[] getExportAddressTable() { | |
710 return (int[]) exportAddressTable.getValue(); | |
711 } | |
712 } | |
713 | |
714 class ExportNameTable { | |
715 private MemoizedObject[] names; | |
716 | |
717 ExportNameTable(final int[] exportNamePointerTable) { | |
718 names = new MemoizedObject[exportNamePointerTable.length]; | |
719 for (int i = 0; i < exportNamePointerTable.length; i++) { | |
720 final int idx = i; | |
721 names[idx] = new MemoizedObject() { | |
722 public Object computeValue() { | |
723 seek(exportNamePointerTable[idx]); | |
724 return readCString(); | |
725 } | |
726 }; | |
727 }; | |
728 } | |
729 | |
730 String get(int i) { | |
731 return (String) names[i].getValue(); | |
732 } | |
733 } | |
734 | |
735 class DebugDirectoryImpl implements DebugDirectory { | |
736 private int offset; | |
737 private int size; | |
738 private int numEntries; | |
739 | |
740 private static final int DEBUG_DIRECTORY_ENTRY_SIZE = 28; | |
741 | |
742 DebugDirectoryImpl(int offset, int size) { | |
743 this.offset = offset; | |
744 this.size = size; | |
745 | |
746 if ((size % DEBUG_DIRECTORY_ENTRY_SIZE) != 0) { | |
747 throw new COFFException("Corrupt DebugDirectory at offset 0x" + | |
748 Integer.toHexString(offset)); | |
749 } | |
750 | |
751 numEntries = size / DEBUG_DIRECTORY_ENTRY_SIZE; | |
752 } | |
753 | |
754 public int getNumEntries() { return numEntries; } | |
755 public DebugDirectoryEntry getEntry(int i) { | |
756 if ((i < 0) || (i >= getNumEntries())) throw new IndexOutOfBoundsException(); | |
757 return new DebugDirectoryEntryImpl(offset + i * DEBUG_DIRECTORY_ENTRY_SIZE); | |
758 } | |
759 } | |
760 | |
761 class DebugDirectoryEntryImpl implements DebugDirectoryEntry, DebugTypes { | |
762 private int characteristics; | |
763 private int timeDateStamp; | |
764 private short majorVersion; | |
765 private short minorVersion; | |
766 private int type; | |
767 private int sizeOfData; | |
768 private int addressOfRawData; | |
769 private int pointerToRawData; | |
770 | |
771 DebugDirectoryEntryImpl(int offset) { | |
772 seek(offset); | |
773 characteristics = readInt(); | |
774 timeDateStamp = readInt(); | |
775 majorVersion = readShort(); | |
776 minorVersion = readShort(); | |
777 type = readInt(); | |
778 sizeOfData = readInt(); | |
779 addressOfRawData = readInt(); | |
780 pointerToRawData = readInt(); | |
781 } | |
782 | |
783 public int getCharacteristics() { return characteristics; } | |
784 public int getTimeDateStamp() { return timeDateStamp; } | |
785 public short getMajorVersion() { return majorVersion; } | |
786 public short getMinorVersion() { return minorVersion; } | |
787 public int getType() { return type; } | |
788 public int getSizeOfData() { return sizeOfData; } | |
789 public int getAddressOfRawData() { return addressOfRawData; } | |
790 public int getPointerToRawData() { return pointerToRawData; } | |
791 | |
792 public DebugVC50 getDebugVC50() { | |
793 // See whether we can recognize VC++ 5.0 debug information. | |
794 try { | |
795 if (getType() != IMAGE_DEBUG_TYPE_CODEVIEW) return null; | |
796 | |
797 int offset = getPointerToRawData(); | |
798 seek(offset); | |
799 if (readByte() == 'N' && | |
800 readByte() == 'B' && | |
801 readByte() == '1' && | |
802 readByte() == '1') { | |
803 return new DebugVC50Impl(offset); | |
804 } | |
805 } catch (COFFException e) { | |
806 e.printStackTrace(); | |
807 } | |
808 return null; | |
809 } | |
810 | |
811 public byte getRawDataByte(int i) { | |
812 if (i < 0 || i >= getSizeOfData()) { | |
813 throw new IndexOutOfBoundsException(); | |
814 } | |
815 seek(getPointerToRawData() + i); | |
816 return readByte(); | |
817 } | |
818 } | |
819 | |
820 class DebugVC50Impl implements DebugVC50, DebugVC50TypeLeafIndices { | |
821 private int lfaBase; | |
822 | |
823 private int subsectionDirectoryOffset; | |
824 private MemoizedObject subsectionDirectory; | |
825 | |
826 DebugVC50Impl(int offset) { | |
827 lfaBase = offset; | |
828 seek(offset); | |
829 readInt(); // Discard NB11 | |
830 subsectionDirectoryOffset = globalOffset(readInt()); | |
831 | |
832 // Ensure information is complete | |
833 verify(); | |
834 | |
835 subsectionDirectory = new MemoizedObject() { | |
836 public Object computeValue() { | |
837 return new DebugVC50SubsectionDirectoryImpl(getSubsectionDirectoryOffset()); | |
838 } | |
839 }; | |
840 } | |
841 | |
842 public int getSubsectionDirectoryOffset() { | |
843 return subsectionDirectoryOffset; | |
844 } | |
845 | |
846 public DebugVC50SubsectionDirectory getSubsectionDirectory() { | |
847 return (DebugVC50SubsectionDirectory) subsectionDirectory.getValue(); | |
848 } | |
849 | |
850 private int globalOffset(int offset) { | |
851 return offset + lfaBase; | |
852 } | |
853 | |
854 private void verify() { | |
855 // Seek to subsection directory manually and look for | |
856 // signature following it. This finishes validating that we | |
857 // have VC++ 5.0 debug info. Throw COFFException if not | |
858 // found; will cause caller to return null. | |
859 seek(subsectionDirectoryOffset); | |
860 int headerLength = readShort(); | |
861 int entryLength = readShort(); | |
862 int numEntries = readInt(); | |
863 int endOffset = subsectionDirectoryOffset + headerLength + numEntries * entryLength; | |
864 seek(endOffset); | |
865 | |
866 if (readByte() == 'N' && | |
867 readByte() == 'B' && | |
868 readByte() == '1' && | |
869 readByte() == '1') { | |
870 return; | |
871 } | |
872 | |
873 throw new COFFException("Did not find NB11 signature at end of debug info"); | |
874 } | |
875 | |
876 class DebugVC50SubsectionDirectoryImpl | |
877 implements DebugVC50SubsectionDirectory, | |
878 DebugVC50SubsectionTypes { | |
879 private int offset; | |
880 private short dirHeaderLength; | |
881 private short dirEntryLength; | |
882 private int numEntries; | |
883 | |
884 DebugVC50SubsectionDirectoryImpl(int offset) { | |
885 this.offset = offset; | |
886 // Read header | |
887 seek(offset); | |
888 dirHeaderLength = readShort(); | |
889 dirEntryLength = readShort(); | |
890 numEntries = readInt(); | |
891 } | |
892 | |
893 public short getHeaderLength() { return dirHeaderLength; } | |
894 public short getEntryLength() { return dirEntryLength; } | |
895 public int getNumEntries() { return numEntries; } | |
896 | |
897 public DebugVC50Subsection getSubsection(int i) { | |
898 // Fetch the subsection type and instantiate the correct | |
899 // type of subsection based on it | |
900 seek(offset + dirHeaderLength + (i * dirEntryLength)); | |
901 short ssType = readShort(); | |
902 short iMod = readShort(); // Unneeded? | |
903 int lfo = globalOffset(readInt()); | |
904 int cb = readInt(); | |
905 switch (ssType) { | |
906 case SST_MODULE: | |
907 return new DebugVC50SSModuleImpl(ssType, iMod, cb, lfo); | |
908 case SST_TYPES: | |
909 return new DebugVC50SSTypesImpl(ssType, iMod, cb, lfo); | |
910 case SST_PUBLIC: | |
911 return new DebugVC50SSPublicImpl(ssType, iMod, cb, lfo); | |
912 case SST_PUBLIC_SYM: | |
913 return new DebugVC50SSPublicSymImpl(ssType, iMod, cb, lfo); | |
914 case SST_SYMBOLS: | |
915 return new DebugVC50SSSymbolsImpl(ssType, iMod, cb, lfo); | |
916 case SST_ALIGN_SYM: | |
917 return new DebugVC50SSAlignSymImpl(ssType, iMod, cb, lfo); | |
918 case SST_SRC_LN_SEG: | |
919 return new DebugVC50SSSrcLnSegImpl(ssType, iMod, cb, lfo); | |
920 case SST_SRC_MODULE: | |
921 return new DebugVC50SSSrcModuleImpl(ssType, iMod, cb, lfo); | |
922 case SST_LIBRARIES: | |
923 return new DebugVC50SSLibrariesImpl(ssType, iMod, cb, lfo); | |
924 case SST_GLOBAL_SYM: | |
925 return new DebugVC50SSGlobalSymImpl(ssType, iMod, cb, lfo); | |
926 case SST_GLOBAL_PUB: | |
927 return new DebugVC50SSGlobalPubImpl(ssType, iMod, cb, lfo); | |
928 case SST_GLOBAL_TYPES: | |
929 return new DebugVC50SSGlobalTypesImpl(ssType, iMod, cb, lfo); | |
930 case SST_MPC: | |
931 return new DebugVC50SSMPCImpl(ssType, iMod, cb, lfo); | |
932 case SST_SEG_MAP: | |
933 return new DebugVC50SSSegMapImpl(ssType, iMod, cb, lfo); | |
934 case SST_SEG_NAME: | |
935 return new DebugVC50SSSegNameImpl(ssType, iMod, cb, lfo); | |
936 case SST_PRE_COMP: | |
937 return new DebugVC50SSPreCompImpl(ssType, iMod, cb, lfo); | |
938 case SST_UNUSED: | |
939 return null; | |
940 case SST_OFFSET_MAP_16: | |
941 return new DebugVC50SSOffsetMap16Impl(ssType, iMod, cb, lfo); | |
942 case SST_OFFSET_MAP_32: | |
943 return new DebugVC50SSOffsetMap32Impl(ssType, iMod, cb, lfo); | |
944 case SST_FILE_INDEX: | |
945 return new DebugVC50SSFileIndexImpl(ssType, iMod, cb, lfo); | |
946 case SST_STATIC_SYM: | |
947 return new DebugVC50SSStaticSymImpl(ssType, iMod, cb, lfo); | |
948 default: | |
949 throw new COFFException("Unknown section type " + ssType); | |
950 } | |
951 } | |
952 } | |
953 | |
954 //////////////////////////////////// | |
955 // // | |
956 // Implementations of subsections // | |
957 // // | |
958 //////////////////////////////////// | |
959 | |
960 class DebugVC50SubsectionImpl implements DebugVC50Subsection { | |
961 private short ssType; | |
962 private short iMod; | |
963 private int ssSize; | |
964 | |
965 DebugVC50SubsectionImpl(short ssType, short iMod, int ssSize, int offset) { | |
966 this.ssType = ssType; | |
967 this.iMod = iMod; | |
968 this.ssSize = ssSize; | |
969 } | |
970 | |
971 public short getSubsectionType() { return ssType; } | |
972 public short getSubsectionModuleIndex() { return iMod; } | |
973 public int getSubsectionSize() { return ssSize; } | |
974 } | |
975 | |
976 class DebugVC50SSModuleImpl extends DebugVC50SubsectionImpl implements DebugVC50SSModule { | |
977 private int offset; | |
978 private short ovlNumber; | |
979 private short iLib; | |
980 private short cSeg; | |
981 private short style; | |
982 private MemoizedObject segInfo; | |
983 private MemoizedObject name; | |
984 | |
985 private static final int HEADER_SIZE = 8; | |
986 private static final int SEG_INFO_SIZE = 12; | |
987 | |
988 DebugVC50SSModuleImpl(short ssType, short iMod, int ssSize, final int offset) { | |
989 super(ssType, iMod, ssSize, offset); | |
990 this.offset = offset; | |
991 seek(offset); | |
992 ovlNumber = readShort(); | |
993 iLib = readShort(); | |
994 cSeg = readShort(); | |
995 style = readShort(); | |
996 segInfo = new MemoizedObject() { | |
997 public Object computeValue() { | |
998 int base = offset + HEADER_SIZE; | |
999 DebugVC50SegInfo[] res = new DebugVC50SegInfo[cSeg]; | |
1000 for (int i = 0; i < cSeg; i++) { | |
1001 res[i] = new DebugVC50SegInfoImpl(base); | |
1002 base += SEG_INFO_SIZE; | |
1003 } | |
1004 return res; | |
1005 } | |
1006 }; | |
1007 name = new MemoizedObject() { | |
1008 public Object computeValue() { | |
1009 return readLengthPrefixedStringAt(offset + (HEADER_SIZE + cSeg * SEG_INFO_SIZE)); | |
1010 } | |
1011 }; | |
1012 } | |
1013 | |
1014 public short getOverlayNumber() { return ovlNumber; } | |
1015 public short getLibrariesIndex() { return iLib; } | |
1016 public short getNumCodeSegments() { return cSeg; } | |
1017 public short getDebuggingStyle() { return style; } | |
1018 public DebugVC50SegInfo getSegInfo(int i) { return ((DebugVC50SegInfo[]) segInfo.getValue())[i]; } | |
1019 public String getName() { return (String) name.getValue(); } | |
1020 } | |
1021 | |
1022 class DebugVC50SegInfoImpl implements DebugVC50SegInfo { | |
1023 private short seg; | |
1024 private int offset; | |
1025 private int cbSeg; | |
1026 | |
1027 DebugVC50SegInfoImpl(int offset) { | |
1028 seek(offset); | |
1029 seg = readShort(); | |
1030 readShort(); // pad | |
1031 offset = readInt(); | |
1032 cbSeg = readInt(); | |
1033 } | |
1034 | |
1035 public short getSegment() { return seg; } | |
1036 public int getOffset() { return offset; } | |
1037 public int getSegmentCodeSize() { return cbSeg; } | |
1038 } | |
1039 | |
1040 class DebugVC50SSTypesImpl extends DebugVC50SubsectionImpl implements DebugVC50SSTypes { | |
1041 DebugVC50SSTypesImpl(short ssType, short iMod, int ssSize, int offset) { | |
1042 super(ssType, iMod, ssSize, offset); | |
1043 } | |
1044 } | |
1045 | |
1046 class DebugVC50SSPublicImpl extends DebugVC50SubsectionImpl implements DebugVC50SSPublic { | |
1047 DebugVC50SSPublicImpl(short ssType, short iMod, int ssSize, int offset) { | |
1048 super(ssType, iMod, ssSize, offset); | |
1049 } | |
1050 } | |
1051 | |
1052 class DebugVC50SSPublicSymImpl extends DebugVC50SubsectionImpl implements DebugVC50SSPublicSym { | |
1053 DebugVC50SSPublicSymImpl(short ssType, short iMod, int ssSize, int offset) { | |
1054 super(ssType, iMod, ssSize, offset); | |
1055 } | |
1056 } | |
1057 | |
1058 class DebugVC50SSSymbolsImpl extends DebugVC50SubsectionImpl implements DebugVC50SSSymbols { | |
1059 DebugVC50SSSymbolsImpl(short ssType, short iMod, int ssSize, int offset) { | |
1060 super(ssType, iMod, ssSize, offset); | |
1061 } | |
1062 } | |
1063 | |
1064 class DebugVC50SSAlignSymImpl extends DebugVC50SubsectionImpl implements DebugVC50SSAlignSym { | |
1065 private int offset; | |
1066 | |
1067 DebugVC50SSAlignSymImpl(short ssType, short iMod, int ssSize, int offset) { | |
1068 super(ssType, iMod, ssSize, offset); | |
1069 this.offset = offset; | |
1070 } | |
1071 | |
1072 public DebugVC50SymbolIterator getSymbolIterator() { | |
1073 return new DebugVC50SymbolIteratorImpl(offset, getSubsectionSize()); | |
1074 } | |
1075 } | |
1076 | |
1077 class DebugVC50SSSrcLnSegImpl extends DebugVC50SubsectionImpl implements DebugVC50SSSrcLnSeg { | |
1078 DebugVC50SSSrcLnSegImpl(short ssType, short iMod, int ssSize, int offset) { | |
1079 super(ssType, iMod, ssSize, offset); | |
1080 } | |
1081 } | |
1082 | |
1083 class DebugVC50SSSrcModuleImpl extends DebugVC50SubsectionImpl implements DebugVC50SSSrcModule { | |
1084 private int offset; | |
1085 private short cFile; | |
1086 private short cSeg; | |
1087 private MemoizedObject baseSrcFiles; | |
1088 private MemoizedObject segOffsets; | |
1089 private MemoizedObject segs; | |
1090 | |
1091 DebugVC50SSSrcModuleImpl(short ssType, short iMod, int ssSize, final int offset) { | |
1092 super(ssType, iMod, ssSize, offset); | |
1093 | |
1094 this.offset = offset; | |
1095 seek(offset); | |
1096 cFile = readShort(); | |
1097 cSeg = readShort(); | |
1098 | |
1099 baseSrcFiles = new MemoizedObject() { | |
1100 public Object computeValue() { | |
1101 int[] offsets = new int[getNumSourceFiles()]; | |
1102 seek(offset + 4); | |
1103 for (int i = 0; i < getNumSourceFiles(); i++) { | |
1104 offsets[i] = offset + readInt(); | |
1105 } | |
1106 DebugVC50SrcModFileDescImpl[] res = new DebugVC50SrcModFileDescImpl[offsets.length]; | |
1107 for (int i = 0; i < res.length; i++) { | |
1108 res[i] = new DebugVC50SrcModFileDescImpl(offsets[i], offset); | |
1109 } | |
1110 return res; | |
1111 } | |
1112 }; | |
1113 | |
1114 segOffsets = new MemoizedObject() { | |
1115 public Object computeValue() { | |
1116 seek(offset + 4 * (getNumSourceFiles() + 1)); | |
1117 int[] res = new int[2 * getNumCodeSegments()]; | |
1118 for (int i = 0; i < 2 * getNumCodeSegments(); i++) { | |
1119 res[i] = readInt(); | |
1120 } | |
1121 return res; | |
1122 } | |
1123 }; | |
1124 | |
1125 segs = new MemoizedObject() { | |
1126 public Object computeValue() { | |
1127 seek(offset + 4 * (getNumSourceFiles() + 1) + 8 * getNumCodeSegments()); | |
1128 short[] res = new short[getNumCodeSegments()]; | |
1129 for (int i = 0; i < getNumCodeSegments(); i++) { | |
1130 res[i] = readShort(); | |
1131 } | |
1132 return res; | |
1133 } | |
1134 }; | |
1135 } | |
1136 | |
1137 public int getNumSourceFiles() { return cFile & 0xFFFF; } | |
1138 public int getNumCodeSegments() { return cSeg & 0xFFFF; } | |
1139 public DebugVC50SrcModFileDesc getSourceFileDesc(int i) { | |
1140 return ((DebugVC50SrcModFileDescImpl[]) baseSrcFiles.getValue())[i]; | |
1141 } | |
1142 | |
1143 public int getSegmentStartOffset(int i) { | |
1144 return ((int[]) segOffsets.getValue())[2*i]; | |
1145 } | |
1146 | |
1147 public int getSegmentEndOffset(int i) { | |
1148 return ((int[]) segOffsets.getValue())[2*i+1]; | |
1149 } | |
1150 | |
1151 public int getSegment(int i) { | |
1152 return ((short[]) segs.getValue())[i] & 0xFFFF; | |
1153 } | |
1154 } | |
1155 | |
1156 class DebugVC50SrcModFileDescImpl implements DebugVC50SrcModFileDesc { | |
1157 private short cSeg; | |
1158 private MemoizedObject baseSrcLn; | |
1159 private MemoizedObject segOffsets; | |
1160 private MemoizedObject name; | |
1161 | |
1162 DebugVC50SrcModFileDescImpl(final int offset, final int baseOffset) { | |
1163 seek(offset); | |
1164 cSeg = readShort(); | |
1165 | |
1166 baseSrcLn = new MemoizedObject() { | |
1167 public Object computeValue() { | |
1168 seek(offset + 4); | |
1169 int[] offsets = new int[getNumCodeSegments()]; | |
1170 for (int i = 0; i < getNumCodeSegments(); i++) { | |
1171 offsets[i] = baseOffset + readInt(); | |
1172 } | |
1173 DebugVC50SrcModLineNumberMapImpl[] res = | |
1174 new DebugVC50SrcModLineNumberMapImpl[getNumCodeSegments()]; | |
1175 for (int i = 0; i < getNumCodeSegments(); i++) { | |
1176 res[i] = new DebugVC50SrcModLineNumberMapImpl(offsets[i]); | |
1177 } | |
1178 return res; | |
1179 } | |
1180 }; | |
1181 | |
1182 segOffsets = new MemoizedObject() { | |
1183 public Object computeValue() { | |
1184 seek(offset + 4 * (getNumCodeSegments() + 1)); | |
1185 int[] res = new int[2 * getNumCodeSegments()]; | |
1186 for (int i = 0; i < 2 * getNumCodeSegments(); i++) { | |
1187 res[i] = readInt(); | |
1188 } | |
1189 return res; | |
1190 } | |
1191 }; | |
1192 | |
1193 name = new MemoizedObject() { | |
1194 public Object computeValue() { | |
1195 seek(offset + 4 + 12 * getNumCodeSegments()); | |
1196 // NOTE: spec says name length is two bytes, but it's really one | |
1197 int cbName = readByte() & 0xFF; | |
1198 byte[] res = new byte[cbName]; | |
1199 readBytes(res); | |
1200 try { | |
1201 return new String(res, US_ASCII); | |
1202 } catch (UnsupportedEncodingException e) { | |
1203 throw new COFFException(e); | |
1204 } | |
1205 } | |
1206 }; | |
1207 } | |
1208 | |
1209 public int getNumCodeSegments() { return cSeg & 0xFFFF; } | |
1210 | |
1211 public DebugVC50SrcModLineNumberMap getLineNumberMap(int i) { | |
1212 return ((DebugVC50SrcModLineNumberMapImpl[]) baseSrcLn.getValue())[i]; | |
1213 } | |
1214 | |
1215 public int getSegmentStartOffset(int i) { | |
1216 return ((int[]) segOffsets.getValue())[2*i]; | |
1217 } | |
1218 | |
1219 public int getSegmentEndOffset(int i) { | |
1220 return ((int[]) segOffsets.getValue())[2*i+1]; | |
1221 } | |
1222 | |
1223 public String getSourceFileName() { | |
1224 return (String) name.getValue(); | |
1225 } | |
1226 } | |
1227 | |
1228 class DebugVC50SrcModLineNumberMapImpl implements DebugVC50SrcModLineNumberMap { | |
1229 private short seg; | |
1230 private short cPair; | |
1231 private MemoizedObject offsets; | |
1232 private MemoizedObject lineNumbers; | |
1233 | |
1234 DebugVC50SrcModLineNumberMapImpl(final int offset) { | |
1235 seek(offset); | |
1236 seg = readShort(); | |
1237 cPair = readShort(); | |
1238 offsets = new MemoizedObject() { | |
1239 public Object computeValue() { | |
1240 seek(offset + 4); | |
1241 int[] res = new int[getNumSourceLinePairs()]; | |
1242 for (int i = 0; i < getNumSourceLinePairs(); i++) { | |
1243 res[i] = readInt(); | |
1244 } | |
1245 return res; | |
1246 } | |
1247 }; | |
1248 | |
1249 lineNumbers = new MemoizedObject() { | |
1250 public Object computeValue() { | |
1251 seek(offset + 4 * (getNumSourceLinePairs() + 1)); | |
1252 short[] res = new short[getNumSourceLinePairs()]; | |
1253 for (int i = 0; i < getNumSourceLinePairs(); i++) { | |
1254 res[i] = readShort(); | |
1255 } | |
1256 return res; | |
1257 } | |
1258 }; | |
1259 } | |
1260 | |
1261 public int getSegment() { return seg; } | |
1262 public int getNumSourceLinePairs() { return cPair; } | |
1263 public int getCodeOffset(int i) { | |
1264 return ((int[]) offsets.getValue())[i]; | |
1265 } | |
1266 public int getLineNumber(int i) { | |
1267 return ((short[]) lineNumbers.getValue())[i] & 0xFFFF; | |
1268 } | |
1269 } | |
1270 | |
1271 class DebugVC50SSLibrariesImpl extends DebugVC50SubsectionImpl implements DebugVC50SSLibraries { | |
1272 DebugVC50SSLibrariesImpl(short ssType, short iMod, int ssSize, int offset) { | |
1273 super(ssType, iMod, ssSize, offset); | |
1274 } | |
1275 | |
1276 // FIXME: NOT FINISHED | |
1277 } | |
1278 | |
1279 class DebugVC50SSSymbolBaseImpl extends DebugVC50SubsectionImpl implements DebugVC50SSSymbolBase { | |
1280 private int offset; | |
1281 private short symHash; | |
1282 private short addrHash; | |
1283 private int cbSymbol; | |
1284 private int cbSymHash; | |
1285 private int cbAddrHash; | |
1286 | |
1287 private static final int HEADER_SIZE = 16; | |
1288 | |
1289 DebugVC50SSSymbolBaseImpl(short ssType, short iMod, int ssSize, int offset) { | |
1290 super(ssType, iMod, ssSize, offset); | |
1291 this.offset = offset; | |
1292 seek(offset); | |
1293 symHash = readShort(); | |
1294 addrHash = readShort(); | |
1295 cbSymbol = readInt(); | |
1296 cbSymHash = readInt(); | |
1297 cbAddrHash = readInt(); | |
1298 } | |
1299 | |
1300 public short getSymHashIndex() { return symHash; } | |
1301 public short getAddrHashIndex() { return addrHash; } | |
1302 public int getSymTabSize() { return cbSymbol; } | |
1303 public int getSymHashSize() { return cbSymHash; } | |
1304 public int getAddrHashSize() { return cbAddrHash; } | |
1305 | |
1306 public DebugVC50SymbolIterator getSymbolIterator() { | |
1307 return new DebugVC50SymbolIteratorImpl(offset + HEADER_SIZE, cbSymbol); | |
1308 } | |
1309 } | |
1310 | |
1311 class DebugVC50SSGlobalSymImpl extends DebugVC50SSSymbolBaseImpl implements DebugVC50SSGlobalSym { | |
1312 DebugVC50SSGlobalSymImpl(short ssType, short iMod, int ssSize, int offset) { | |
1313 super(ssType, iMod, ssSize, offset); | |
1314 } | |
1315 } | |
1316 class DebugVC50SSGlobalPubImpl extends DebugVC50SSSymbolBaseImpl implements DebugVC50SSGlobalPub { | |
1317 DebugVC50SSGlobalPubImpl(short ssType, short iMod, int ssSize, int offset) { | |
1318 super(ssType, iMod, ssSize, offset); | |
1319 } | |
1320 } | |
1321 | |
1322 class DebugVC50SSGlobalTypesImpl extends DebugVC50SubsectionImpl implements DebugVC50SSGlobalTypes { | |
1323 private int offset; | |
1324 private int cType; | |
1325 | |
1326 DebugVC50SSGlobalTypesImpl(short ssType, short iMod, int ssSize, int offset) { | |
1327 super(ssType, iMod, ssSize, offset); | |
1328 this.offset = offset; | |
1329 seek(offset); | |
1330 readInt(); // Discard "flags" | |
1331 cType = readInt(); | |
1332 } | |
1333 | |
1334 public int getNumTypes() { return cType; } | |
1335 // FIXME: should memoize these | |
1336 public int getTypeOffset(int i) { | |
1337 seek(offset + 4 * (i + 2)); | |
1338 return readInt() + offsetOfFirstType(); | |
1339 } | |
1340 | |
1341 public DebugVC50TypeIterator getTypeIterator() { | |
1342 return new DebugVC50TypeIteratorImpl(this, | |
1343 offsetOfFirstType(), | |
1344 cType); | |
1345 } | |
1346 | |
1347 private int offsetOfFirstType() { | |
1348 return offset + 4 * (getNumTypes() + 2); | |
1349 } | |
1350 } | |
1351 | |
1352 class DebugVC50SSMPCImpl extends DebugVC50SubsectionImpl implements DebugVC50SSMPC { | |
1353 DebugVC50SSMPCImpl(short ssType, short iMod, int ssSize, int offset) { | |
1354 super(ssType, iMod, ssSize, offset); | |
1355 } | |
1356 } | |
1357 | |
1358 class DebugVC50SSSegMapImpl extends DebugVC50SubsectionImpl implements DebugVC50SSSegMap { | |
1359 private short cSeg; | |
1360 private short cSegLog; | |
1361 private MemoizedObject segDescs; | |
1362 | |
1363 DebugVC50SSSegMapImpl(short ssType, short iMod, int ssSize, final int offset) { | |
1364 super(ssType, iMod, ssSize, offset); | |
1365 seek(offset); | |
1366 cSeg = readShort(); | |
1367 cSegLog = readShort(); | |
1368 segDescs = new MemoizedObject() { | |
1369 public Object computeValue() { | |
1370 DebugVC50SegDesc[] descs = new DebugVC50SegDesc[cSeg]; | |
1371 for (int i = 0; i < cSeg; i++) { | |
1372 descs[i] = new DebugVC50SegDescImpl(offset + 4 + (20 * i)); | |
1373 } | |
1374 return descs; | |
1375 } | |
1376 }; | |
1377 } | |
1378 | |
1379 public short getNumSegDesc() { return cSeg; } | |
1380 public short getNumLogicalSegDesc() { return cSegLog; } | |
1381 public DebugVC50SegDesc getSegDesc(int i) { return ((DebugVC50SegDesc[]) segDescs.getValue())[i]; } | |
1382 } | |
1383 | |
1384 class DebugVC50SegDescImpl implements DebugVC50SegDesc { | |
1385 private short flags; | |
1386 private short ovl; | |
1387 private short group; | |
1388 private short frame; | |
1389 private short iSegName; | |
1390 private short iClassName; | |
1391 private int offset; | |
1392 private int cbSeg; | |
1393 | |
1394 DebugVC50SegDescImpl(int offset) { | |
1395 seek(offset); | |
1396 flags = readShort(); | |
1397 ovl = readShort(); | |
1398 group = readShort(); | |
1399 frame = readShort(); | |
1400 iSegName = readShort(); | |
1401 iClassName = readShort(); | |
1402 offset = readInt(); | |
1403 cbSeg = readInt(); | |
1404 } | |
1405 | |
1406 public short getFlags() { return flags; } | |
1407 public short getOverlayNum() { return ovl; } | |
1408 public short getGroup() { return group; } | |
1409 public short getFrame() { return frame; } | |
1410 public short getName() { return iSegName; } | |
1411 public short getClassName() { return iClassName; } | |
1412 public int getOffset() { return offset; } | |
1413 public int getSize() { return cbSeg; } | |
1414 } | |
1415 | |
1416 | |
1417 class DebugVC50SSSegNameImpl extends DebugVC50SubsectionImpl implements DebugVC50SSSegName { | |
1418 private int offset; | |
1419 private int size; | |
1420 private MemoizedObject names; | |
1421 | |
1422 DebugVC50SSSegNameImpl(short ssType, short iMod, int ssSize, int offset) { | |
1423 super(ssType, iMod, ssSize, offset); | |
1424 this.offset = offset; | |
1425 this.size = ssSize; | |
1426 seek(offset); | |
1427 names = new MemoizedObject() { | |
1428 public Object computeValue() { | |
1429 int i = 0; | |
1430 List data = new ArrayList(); | |
1431 while (i < size) { | |
1432 String s = readCString(); | |
1433 data.add(s); | |
1434 i += s.length(); | |
1435 } | |
1436 String[] res = new String[data.size()]; | |
1437 res = (String[]) data.toArray(res); | |
1438 return res; | |
1439 } | |
1440 }; | |
1441 } | |
1442 | |
1443 public String getSegName(int i) { | |
1444 return ((String[]) names.getValue())[i]; | |
1445 } | |
1446 } | |
1447 | |
1448 class DebugVC50SSPreCompImpl extends DebugVC50SubsectionImpl implements DebugVC50SSPreComp { | |
1449 DebugVC50SSPreCompImpl(short ssType, short iMod, int ssSize, int offset) { | |
1450 super(ssType, iMod, ssSize, offset); | |
1451 } | |
1452 } | |
1453 | |
1454 class DebugVC50SSOffsetMap16Impl extends DebugVC50SubsectionImpl implements DebugVC50SSOffsetMap16 { | |
1455 DebugVC50SSOffsetMap16Impl(short ssType, short iMod, int ssSize, int offset) { | |
1456 super(ssType, iMod, ssSize, offset); | |
1457 } | |
1458 } | |
1459 | |
1460 class DebugVC50SSOffsetMap32Impl extends DebugVC50SubsectionImpl implements DebugVC50SSOffsetMap32 { | |
1461 DebugVC50SSOffsetMap32Impl(short ssType, short iMod, int ssSize, int offset) { | |
1462 super(ssType, iMod, ssSize, offset); | |
1463 } | |
1464 } | |
1465 | |
1466 class DebugVC50SSFileIndexImpl extends DebugVC50SubsectionImpl implements DebugVC50SSFileIndex { | |
1467 private int offset; | |
1468 private short cMod; // Number of modules in the executable | |
1469 private short cRef; // Total number of file name references | |
1470 private MemoizedObject modStart; | |
1471 private MemoizedObject cRefCnt; | |
1472 // FIXME: probably useless; needs fixup to be converted into | |
1473 // indices rather than offsets | |
1474 private MemoizedObject nameRef; | |
1475 private MemoizedObject names; | |
1476 | |
1477 DebugVC50SSFileIndexImpl(short ssType, short iMod, int ssSize, final int offset) { | |
1478 super(ssType, iMod, ssSize, offset); | |
1479 this.offset = offset; | |
1480 seek(offset); | |
1481 cMod = readShort(); | |
1482 cRef = readShort(); | |
1483 modStart = new MemoizedObject() { | |
1484 public Object computeValue() { | |
1485 short[] vals = new short[cMod]; | |
1486 seek(4 + offset); | |
1487 for (int i = 0; i < cMod; i++) { | |
1488 vals[i] = readShort(); | |
1489 } | |
1490 return vals; | |
1491 } | |
1492 }; | |
1493 cRefCnt = new MemoizedObject() { | |
1494 public Object computeValue() { | |
1495 short[] vals = new short[cMod]; | |
1496 seek(4 + offset + (2 * cMod)); | |
1497 for (int i = 0; i < cMod; i++) { | |
1498 vals[i] = readShort(); | |
1499 } | |
1500 return vals; | |
1501 } | |
1502 }; | |
1503 nameRef = new MemoizedObject() { | |
1504 public Object computeValue() { | |
1505 int[] vals = new int[cRef]; | |
1506 seek(4 + offset + (4 * cMod)); | |
1507 for (int i = 0; i < cMod; i++) { | |
1508 vals[i] = readInt(); | |
1509 } | |
1510 return vals; | |
1511 } | |
1512 }; | |
1513 names = new MemoizedObject() { | |
1514 public Object computeValue() { | |
1515 String[] vals = new String[cRef]; | |
1516 for (int i = 0; i < cRef; i++) { | |
1517 vals[i] = readCString(); | |
1518 } | |
1519 return vals; | |
1520 } | |
1521 }; | |
1522 } | |
1523 | |
1524 public short getNumModules() { return cMod; } | |
1525 public short getNumReferences() { return cRef; } | |
1526 public short[] getModStart() { return (short[]) modStart.getValue(); } | |
1527 public short[] getRefCount() { return (short[]) cRefCnt.getValue(); } | |
1528 public int[] getNameRef() { return (int[]) nameRef.getValue(); } | |
1529 public String[] getNames() { return (String[]) names.getValue(); } | |
1530 } | |
1531 | |
1532 class DebugVC50SSStaticSymImpl extends DebugVC50SSSymbolBaseImpl implements DebugVC50SSStaticSym { | |
1533 DebugVC50SSStaticSymImpl(short ssType, short iMod, int ssSize, int offset) { | |
1534 super(ssType, iMod, ssSize, offset); | |
1535 } | |
1536 } | |
1537 | |
1538 ////////////////////////////////////////////////// | |
1539 // // | |
1540 // Implementations of symbol and type iterators // | |
1541 // // | |
1542 ////////////////////////////////////////////////// | |
1543 | |
1544 class DebugVC50SymbolIteratorImpl implements DebugVC50SymbolIterator { | |
1545 private int base; | |
1546 private int size; | |
1547 private int pos; | |
1548 private int curSymSize; | |
1549 private int curSymType; | |
1550 | |
1551 private static final int HEADER_SIZE = 4; | |
1552 | |
1553 DebugVC50SymbolIteratorImpl(int base, int size) { | |
1554 this(base, size, base); | |
1555 } | |
1556 | |
1557 private DebugVC50SymbolIteratorImpl(int base, int size, int pos) { | |
1558 this.base = base; | |
1559 this.size = size; | |
1560 this.pos = pos; | |
1561 seek(pos); | |
1562 curSymSize = readShort() & 0xFFFF; | |
1563 curSymType = readShort() & 0xFFFF; | |
1564 } | |
1565 | |
1566 public boolean done() { | |
1567 return (pos == (base + size)); | |
1568 } | |
1569 | |
1570 public void next() throws NoSuchElementException { | |
1571 if (done()) throw new NoSuchElementException("No more symbols"); | |
1572 pos += curSymSize + 2; | |
1573 seek(pos); | |
1574 curSymSize = readShort() & 0xFFFF; | |
1575 curSymType = readShort() & 0xFFFF; | |
1576 } | |
1577 | |
1578 public short getLength() { | |
1579 return (short) curSymSize; | |
1580 } | |
1581 | |
1582 public int getType() { | |
1583 return curSymType; | |
1584 } | |
1585 | |
1586 public int getOffset() { | |
1587 return pos + HEADER_SIZE; | |
1588 } | |
1589 | |
1590 ///////////////////////// | |
1591 // S_COMPILE accessors // | |
1592 ///////////////////////// | |
1593 | |
1594 public byte getCompilerTargetProcessor() { | |
1595 symSeek(0); | |
1596 return readByte(); | |
1597 } | |
1598 | |
1599 public int getCompilerFlags() { | |
1600 symSeek(1); | |
1601 int res = 0; | |
1602 for (int i = 0; i < 3; i++) { | |
1603 int b = readByte() & 0xFF; | |
1604 res = (res << 8) | b; | |
1605 } | |
1606 return res; | |
1607 } | |
1608 | |
1609 public String getComplierVersion() { | |
1610 return readLengthPrefixedStringAt(4); | |
1611 } | |
1612 | |
1613 ////////////////////////// | |
1614 // S_REGISTER accessors // | |
1615 ////////////////////////// | |
1616 | |
1617 public int getRegisterSymbolType() { | |
1618 symSeek(0); | |
1619 return readInt(); | |
1620 } | |
1621 | |
1622 public short getRegisterEnum() { | |
1623 symSeek(4); | |
1624 return readShort(); | |
1625 } | |
1626 | |
1627 public String getRegisterSymbolName() { | |
1628 return readLengthPrefixedStringAt(6); | |
1629 } | |
1630 | |
1631 ////////////////////////// | |
1632 // S_CONSTANT accessors // | |
1633 ////////////////////////// | |
1634 | |
1635 public int getConstantType() { | |
1636 symSeek(0); | |
1637 return readInt(); | |
1638 } | |
1639 | |
1640 public int getConstantValueAsInt() throws DebugVC50WrongNumericTypeException { | |
1641 return readIntNumericLeafAt(4); | |
1642 } | |
1643 | |
1644 public long getConstantValueAsLong() throws DebugVC50WrongNumericTypeException { | |
1645 return readLongNumericLeafAt(4); | |
1646 } | |
1647 | |
1648 public float getConstantValueAsFloat() throws DebugVC50WrongNumericTypeException { | |
1649 return readFloatNumericLeafAt(4); | |
1650 } | |
1651 | |
1652 public double getConstantValueAsDouble() throws DebugVC50WrongNumericTypeException { | |
1653 return readDoubleNumericLeafAt(4); | |
1654 } | |
1655 | |
1656 public String getConstantName() { | |
1657 return readLengthPrefixedStringAt(4 + numericLeafLengthAt(4)); | |
1658 } | |
1659 | |
1660 ///////////////////// | |
1661 // S_UDT accessors // | |
1662 ///////////////////// | |
1663 | |
1664 public int getUDTType() { | |
1665 symSeek(0); | |
1666 return readInt(); | |
1667 } | |
1668 | |
1669 public String getUDTName() { | |
1670 return readLengthPrefixedStringAt(4); | |
1671 } | |
1672 | |
1673 ///////////////////////// | |
1674 // S_SSEARCH accessors // | |
1675 ///////////////////////// | |
1676 | |
1677 public int getSearchSymbolOffset() { | |
1678 symSeek(0); | |
1679 return readInt(); | |
1680 } | |
1681 | |
1682 public short getSearchSegment() { | |
1683 symSeek(4); | |
1684 return readShort(); | |
1685 } | |
1686 | |
1687 ///////////////////// | |
1688 // S_END accessors // | |
1689 ///////////////////// | |
1690 | |
1691 // (No accessors) | |
1692 | |
1693 ////////////////////// | |
1694 // S_SKIP accessors // | |
1695 ////////////////////// | |
1696 | |
1697 // (No accessors) | |
1698 | |
1699 /////////////////////////// | |
1700 // S_CVRESERVE accessors // | |
1701 /////////////////////////// | |
1702 | |
1703 // (No accessors) | |
1704 | |
1705 ///////////////////////// | |
1706 // S_OBJNAME accessors // | |
1707 ///////////////////////// | |
1708 | |
1709 public int getObjectCodeViewSignature() { | |
1710 symSeek(0); | |
1711 return readInt(); | |
1712 } | |
1713 | |
1714 public String getObjectName() { | |
1715 return readLengthPrefixedStringAt(4); | |
1716 } | |
1717 | |
1718 //////////////////////// | |
1719 // S_ENDARG accessors // | |
1720 //////////////////////// | |
1721 | |
1722 // (No accessors) | |
1723 | |
1724 ////////////////////////// | |
1725 // S_COBOLUDT accessors // | |
1726 ////////////////////////// | |
1727 | |
1728 // (Elided as they are irrelevant) | |
1729 | |
1730 ///////////////////////// | |
1731 // S_MANYREG accessors // | |
1732 ///////////////////////// | |
1733 | |
1734 public int getManyRegType() { | |
1735 symSeek(0); | |
1736 return readInt(); | |
1737 } | |
1738 | |
1739 public byte getManyRegCount() { | |
1740 symSeek(4); | |
1741 return readByte(); | |
1742 } | |
1743 | |
1744 public byte getManyRegRegister(int i) { | |
1745 symSeek(5 + i); | |
1746 return readByte(); | |
1747 } | |
1748 | |
1749 public String getManyRegName() { | |
1750 return readLengthPrefixedStringAt(5 + getManyRegCount()); | |
1751 } | |
1752 | |
1753 //////////////////////// | |
1754 // S_RETURN accessors // | |
1755 //////////////////////// | |
1756 | |
1757 public short getReturnFlags() { | |
1758 symSeek(0); | |
1759 return readShort(); | |
1760 } | |
1761 | |
1762 public byte getReturnStyle() { | |
1763 symSeek(2); | |
1764 return readByte(); | |
1765 } | |
1766 | |
1767 public byte getReturnRegisterCount() { | |
1768 symSeek(3); | |
1769 return readByte(); | |
1770 } | |
1771 | |
1772 public byte getReturnRegister(int i) { | |
1773 symSeek(4 + i); | |
1774 return readByte(); | |
1775 } | |
1776 | |
1777 /////////////////////////// | |
1778 // S_ENTRYTHIS accessors // | |
1779 /////////////////////////// | |
1780 | |
1781 public void advanceToEntryThisSymbol() { | |
1782 seek(pos + 4); | |
1783 int tmpSymSize = readShort(); | |
1784 int tmpSymType = readShort(); | |
1785 if (Assert.ASSERTS_ENABLED) { | |
1786 // Make sure that ends of inner and outer symbols line | |
1787 // up, otherwise need more work | |
1788 Assert.that(pos + curSymSize + 2 == pos + 4 + tmpSymSize, | |
1789 "advanceToEntryThisSymbol needs more work"); | |
1790 } | |
1791 pos += 4; | |
1792 curSymSize = tmpSymSize; | |
1793 curSymType = tmpSymType; | |
1794 } | |
1795 | |
1796 /////////////////////////////////////////////////////////////////////// | |
1797 // // | |
1798 // // | |
1799 // Symbols for (Intel) 16:32 Segmented and 32-bit Flat Architectures // | |
1800 // // | |
1801 // // | |
1802 /////////////////////////////////////////////////////////////////////// | |
1803 | |
1804 ///////////////////////// | |
1805 // S_BPREL32 accessors // | |
1806 ///////////////////////// | |
1807 | |
1808 public int getBPRelOffset() { | |
1809 symSeek(0); | |
1810 return readInt(); | |
1811 } | |
1812 | |
1813 public int getBPRelType() { | |
1814 symSeek(4); | |
1815 return readInt(); | |
1816 } | |
1817 | |
1818 public String getBPRelName() { | |
1819 return readLengthPrefixedStringAt(8); | |
1820 } | |
1821 | |
1822 /////////////////////////////////////// | |
1823 // S_LDATA32 and S_GDATA32 accessors // | |
1824 /////////////////////////////////////// | |
1825 | |
1826 public int getLGDataType() { | |
1827 symSeek(0); | |
1828 return readInt(); | |
1829 } | |
1830 | |
1831 public int getLGDataOffset() { | |
1832 symSeek(4); | |
1833 return readInt(); | |
1834 } | |
1835 | |
1836 public short getLGDataSegment() { | |
1837 symSeek(8); | |
1838 return readShort(); | |
1839 } | |
1840 | |
1841 public String getLGDataName() { | |
1842 return readLengthPrefixedStringAt(10); | |
1843 } | |
1844 | |
1845 /////////////////////// | |
1846 // S_PUB32 accessors // | |
1847 /////////////////////// | |
1848 | |
1849 // FIXME: has the same format as the above; consider updating | |
1850 // documentation. No separate accessors provided. | |
1851 | |
1852 /////////////////////////////////////// | |
1853 // S_LPROC32 and S_GPROC32 accessors // | |
1854 /////////////////////////////////////// | |
1855 | |
1856 public DebugVC50SymbolIterator getLGProcParent() { | |
1857 int offs = getLGProcParentOffset(); | |
1858 if (offs == 0) return null; | |
1859 return new DebugVC50SymbolIteratorImpl(base, size, offs); | |
1860 } | |
1861 | |
1862 public int getLGProcParentOffset() { | |
1863 symSeek(0); | |
1864 int offs = readInt(); | |
1865 if (offs == 0) return 0; | |
1866 return base + offs; | |
1867 } | |
1868 | |
1869 public DebugVC50SymbolIterator getLGProcEnd() { | |
1870 int offs = getLGProcEndOffset(); | |
1871 return new DebugVC50SymbolIteratorImpl(base, size, offs); | |
1872 } | |
1873 | |
1874 public int getLGProcEndOffset() { | |
1875 symSeek(4); | |
1876 int offs = readInt(); | |
1877 if (Assert.ASSERTS_ENABLED) { | |
1878 Assert.that(offs != 0, "should not have null end offset for procedure symbols"); | |
1879 } | |
1880 return base + offs; | |
1881 } | |
1882 | |
1883 public DebugVC50SymbolIterator getLGProcNext() { | |
1884 int offs = getLGProcNextOffset(); | |
1885 if (offs == 0) return null; | |
1886 return new DebugVC50SymbolIteratorImpl(base, size, offs); | |
1887 } | |
1888 | |
1889 public int getLGProcNextOffset() { | |
1890 symSeek(8); | |
1891 int offs = readInt(); | |
1892 if (offs == 0) return 0; | |
1893 return base + offs; | |
1894 } | |
1895 | |
1896 public int getLGProcLength() { | |
1897 symSeek(12); | |
1898 return readInt(); | |
1899 } | |
1900 | |
1901 public int getLGProcDebugStart() { | |
1902 symSeek(16); | |
1903 return readInt(); | |
1904 } | |
1905 | |
1906 public int getLGProcDebugEnd() { | |
1907 symSeek(20); | |
1908 return readInt(); | |
1909 } | |
1910 | |
1911 public int getLGProcType() { | |
1912 symSeek(24); | |
1913 return readInt(); | |
1914 } | |
1915 | |
1916 public int getLGProcOffset() { | |
1917 symSeek(28); | |
1918 return readInt(); | |
1919 } | |
1920 | |
1921 public short getLGProcSegment() { | |
1922 symSeek(32); | |
1923 return readShort(); | |
1924 } | |
1925 | |
1926 public byte getLGProcFlags() { | |
1927 symSeek(34); | |
1928 return readByte(); | |
1929 } | |
1930 | |
1931 public String getLGProcName() { | |
1932 return readLengthPrefixedStringAt(35); | |
1933 } | |
1934 | |
1935 ///////////////////////// | |
1936 // S_THUNK32 accessors // | |
1937 ///////////////////////// | |
1938 | |
1939 public DebugVC50SymbolIterator getThunkParent() { | |
1940 int offs = getThunkParentOffset(); | |
1941 if (offs == 0) return null; | |
1942 return new DebugVC50SymbolIteratorImpl(base, size, offs); | |
1943 } | |
1944 | |
1945 public int getThunkParentOffset() { | |
1946 symSeek(0); | |
1947 int offs = readInt(); | |
1948 if (offs == 0) return 0; | |
1949 return base + offs; | |
1950 } | |
1951 | |
1952 public DebugVC50SymbolIterator getThunkEnd() { | |
1953 symSeek(4); | |
1954 int offs = readInt(); | |
1955 return new DebugVC50SymbolIteratorImpl(base, size, offs); | |
1956 } | |
1957 | |
1958 public int getThunkEndOffset() { | |
1959 symSeek(4); | |
1960 int offs = readInt(); | |
1961 if (Assert.ASSERTS_ENABLED) { | |
1962 Assert.that(offs != 0, "should not have null end offset for thunk symbols"); | |
1963 } | |
1964 return base + offs; | |
1965 } | |
1966 | |
1967 public DebugVC50SymbolIterator getThunkNext() { | |
1968 int offs = getThunkNextOffset(); | |
1969 if (offs == 0) return null; | |
1970 return new DebugVC50SymbolIteratorImpl(base, size, base + offs); | |
1971 } | |
1972 | |
1973 public int getThunkNextOffset() { | |
1974 symSeek(8); | |
1975 int offs = readInt(); | |
1976 if (offs == 0) return 0; | |
1977 return base + offs; | |
1978 } | |
1979 | |
1980 public int getThunkOffset() { | |
1981 symSeek(12); | |
1982 return readInt(); | |
1983 } | |
1984 | |
1985 public short getThunkSegment() { | |
1986 symSeek(16); | |
1987 return readShort(); | |
1988 } | |
1989 | |
1990 public short getThunkLength() { | |
1991 symSeek(18); | |
1992 return readShort(); | |
1993 } | |
1994 | |
1995 public byte getThunkType() { | |
1996 symSeek(20); | |
1997 return readByte(); | |
1998 } | |
1999 | |
2000 public String getThunkName() { | |
2001 return readLengthPrefixedStringAt(21); | |
2002 } | |
2003 | |
2004 public short getThunkAdjustorThisDelta() { | |
2005 symSeek(21 + lengthPrefixedStringLengthAt(21)); | |
2006 return readShort(); | |
2007 } | |
2008 | |
2009 public String getThunkAdjustorTargetName() { | |
2010 return readLengthPrefixedStringAt(23 + lengthPrefixedStringLengthAt(21)); | |
2011 } | |
2012 | |
2013 public short getThunkVCallDisplacement() { | |
2014 symSeek(21 + lengthPrefixedStringLengthAt(21)); | |
2015 return readShort(); | |
2016 } | |
2017 | |
2018 public int getThunkPCodeOffset() { | |
2019 symSeek(21 + lengthPrefixedStringLengthAt(21)); | |
2020 return readInt(); | |
2021 } | |
2022 | |
2023 public short getThunkPCodeSegment() { | |
2024 symSeek(25 + lengthPrefixedStringLengthAt(21)); | |
2025 return readShort(); | |
2026 } | |
2027 | |
2028 ///////////////////////// | |
2029 // S_BLOCK32 accessors // | |
2030 ///////////////////////// | |
2031 | |
2032 public DebugVC50SymbolIterator getBlockParent() { | |
2033 int offs = getBlockParentOffset(); | |
2034 if (offs == 0) return null; | |
2035 return new DebugVC50SymbolIteratorImpl(base, size, offs); | |
2036 } | |
2037 | |
2038 public int getBlockParentOffset() { | |
2039 symSeek(0); | |
2040 int offs = readInt(); | |
2041 if (offs == 0) return 0; | |
2042 return base + offs; | |
2043 } | |
2044 | |
2045 public DebugVC50SymbolIterator getBlockEnd() { | |
2046 symSeek(4); | |
2047 int offs = readInt(); | |
2048 return new DebugVC50SymbolIteratorImpl(base, size, offs); | |
2049 } | |
2050 | |
2051 public int getBlockEndOffset() { | |
2052 symSeek(4); | |
2053 int offs = readInt(); | |
2054 if (Assert.ASSERTS_ENABLED) { | |
2055 Assert.that(offs != 0, "should not have null end offset for block symbols"); | |
2056 } | |
2057 return base + offs; | |
2058 } | |
2059 | |
2060 public int getBlockLength() { | |
2061 symSeek(8); | |
2062 return readInt(); | |
2063 } | |
2064 | |
2065 public int getBlockOffset() { | |
2066 symSeek(12); | |
2067 return readInt(); | |
2068 } | |
2069 | |
2070 public short getBlockSegment() { | |
2071 symSeek(16); | |
2072 return readShort(); | |
2073 } | |
2074 | |
2075 public String getBlockName() { | |
2076 return readLengthPrefixedStringAt(18); | |
2077 } | |
2078 | |
2079 //////////////////////// | |
2080 // S_WITH32 accessors // | |
2081 //////////////////////// | |
2082 | |
2083 // FIXME: this is a Pascal construct; ignored for now | |
2084 | |
2085 ///////////////////////// | |
2086 // S_LABEL32 accessors // | |
2087 ///////////////////////// | |
2088 | |
2089 public int getLabelOffset() { | |
2090 symSeek(0); | |
2091 return readInt(); | |
2092 } | |
2093 | |
2094 public short getLabelSegment() { | |
2095 symSeek(4); | |
2096 return readShort(); | |
2097 } | |
2098 | |
2099 public byte getLabelFlags() { | |
2100 symSeek(6); | |
2101 return readByte(); | |
2102 } | |
2103 | |
2104 public String getLabelName() { | |
2105 return readLengthPrefixedStringAt(7); | |
2106 } | |
2107 | |
2108 //////////////////////////// | |
2109 // S_CEXMODEL32 accessors // | |
2110 //////////////////////////// | |
2111 | |
2112 public int getChangeOffset() { | |
2113 symSeek(0); | |
2114 return readInt(); | |
2115 } | |
2116 | |
2117 public short getChangeSegment() { | |
2118 symSeek(4); | |
2119 return readShort(); | |
2120 } | |
2121 | |
2122 public short getChangeModel() { | |
2123 symSeek(6); | |
2124 return readShort(); | |
2125 } | |
2126 | |
2127 //////////////////////////// | |
2128 // S_VFTTABLE32 accessors // | |
2129 //////////////////////////// | |
2130 | |
2131 public int getVTableRoot() { | |
2132 symSeek(0); | |
2133 return readInt(); | |
2134 } | |
2135 | |
2136 public int getVTablePath() { | |
2137 symSeek(4); | |
2138 return readInt(); | |
2139 } | |
2140 | |
2141 public int getVTableOffset() { | |
2142 symSeek(8); | |
2143 return readInt(); | |
2144 } | |
2145 | |
2146 public short getVTableSegment() { | |
2147 symSeek(12); | |
2148 return readShort(); | |
2149 } | |
2150 | |
2151 ////////////////////////// | |
2152 // S_REGREL32 accessors // | |
2153 ////////////////////////// | |
2154 | |
2155 public int getRegRelOffset() { | |
2156 symSeek(0); | |
2157 return readInt(); | |
2158 } | |
2159 | |
2160 public int getRegRelType() { | |
2161 symSeek(4); | |
2162 return readInt(); | |
2163 } | |
2164 | |
2165 public short getRegRelRegister() { | |
2166 symSeek(8); | |
2167 return readShort(); | |
2168 } | |
2169 | |
2170 public String getRegRelName() { | |
2171 return readLengthPrefixedStringAt(10); | |
2172 } | |
2173 | |
2174 /////////////////////////////////////////// | |
2175 // S_LTHREAD32 and S_GTHREAD32 accessors // | |
2176 /////////////////////////////////////////// | |
2177 | |
2178 public int getLThreadType() { | |
2179 symSeek(0); | |
2180 return readInt(); | |
2181 } | |
2182 | |
2183 public int getLThreadOffset() { | |
2184 symSeek(4); | |
2185 return readInt(); | |
2186 } | |
2187 | |
2188 public short getLThreadSegment() { | |
2189 symSeek(8); | |
2190 return readShort(); | |
2191 } | |
2192 | |
2193 public String getLThreadName() { | |
2194 return readLengthPrefixedStringAt(10); | |
2195 } | |
2196 | |
2197 //---------------------------------------------------------------------- | |
2198 // Internals only below this point | |
2199 // | |
2200 | |
2201 private void symSeek(int offsetInSym) { | |
2202 seek(pos + HEADER_SIZE + offsetInSym); | |
2203 } | |
2204 | |
2205 private int numericLeafLengthAt(int offsetInSym) { | |
2206 return DebugVC50Impl.this.numericLeafLengthAt(pos + HEADER_SIZE + offsetInSym); | |
2207 } | |
2208 | |
2209 private int readIntNumericLeafAt(int offsetInSym) { | |
2210 return DebugVC50Impl.this.readIntNumericLeafAt(pos + HEADER_SIZE + offsetInSym); | |
2211 } | |
2212 | |
2213 private long readLongNumericLeafAt(int offsetInSym) { | |
2214 return DebugVC50Impl.this.readLongNumericLeafAt(pos + HEADER_SIZE + offsetInSym); | |
2215 } | |
2216 | |
2217 private float readFloatNumericLeafAt(int offsetInSym) { | |
2218 return DebugVC50Impl.this.readFloatNumericLeafAt(pos + HEADER_SIZE + offsetInSym); | |
2219 } | |
2220 | |
2221 private double readDoubleNumericLeafAt(int offsetInSym) { | |
2222 return DebugVC50Impl.this.readDoubleNumericLeafAt(pos + HEADER_SIZE + offsetInSym); | |
2223 } | |
2224 | |
2225 private int lengthPrefixedStringLengthAt(int offsetInSym) { | |
2226 return DebugVC50Impl.this.lengthPrefixedStringLengthAt(pos + HEADER_SIZE + offsetInSym); | |
2227 } | |
2228 | |
2229 private String readLengthPrefixedStringAt(int offsetInSym) { | |
2230 return DebugVC50Impl.this.readLengthPrefixedStringAt(pos + HEADER_SIZE + offsetInSym); | |
2231 } | |
2232 } | |
2233 | |
2234 class DebugVC50TypeIteratorImpl implements DebugVC50TypeIterator, | |
2235 DebugVC50TypeLeafIndices, DebugVC50MemberAttributes, DebugVC50TypeEnums { | |
2236 private DebugVC50SSGlobalTypes parent; | |
2237 private int base; | |
2238 private int numTypes; | |
2239 private int typeIndex; | |
2240 private int typeRecordOffset; | |
2241 private int typeStringOffset; | |
2242 private int typeRecordSize; | |
2243 private int typeStringLeaf; | |
2244 | |
2245 DebugVC50TypeIteratorImpl(DebugVC50SSGlobalTypes parent, int base, int numTypes) { | |
2246 this(parent, base, numTypes, 0, base); | |
2247 } | |
2248 | |
2249 private DebugVC50TypeIteratorImpl(DebugVC50SSGlobalTypes parent, int base, int numTypes, int curType, int offset) { | |
2250 this.parent = parent; | |
2251 this.base = base; | |
2252 this.numTypes = numTypes; | |
2253 this.typeIndex = curType; | |
2254 if (!done()) { | |
2255 typeRecordOffset = offset; | |
2256 loadTypeRecord(); | |
2257 } | |
2258 } | |
2259 | |
2260 public boolean done() { | |
2261 return (typeIndex == numTypes); | |
2262 } | |
2263 | |
2264 public void next() throws NoSuchElementException { | |
2265 if (done()) throw new NoSuchElementException(); | |
2266 ++typeIndex; | |
2267 if (!done()) { | |
2268 typeRecordOffset = parent.getTypeOffset(typeIndex); | |
2269 loadTypeRecord(); | |
2270 } | |
2271 } | |
2272 | |
2273 public short getLength() { | |
2274 return (short) typeRecordSize; | |
2275 } | |
2276 | |
2277 public int getTypeIndex() { | |
2278 return biasTypeIndex(typeIndex); | |
2279 } | |
2280 | |
2281 public int getNumTypes() { | |
2282 return numTypes; | |
2283 } | |
2284 | |
2285 public boolean typeStringDone() { | |
2286 return (typeStringOffset - typeRecordOffset - 2) >= typeRecordSize; | |
2287 } | |
2288 | |
2289 public void typeStringNext() throws NoSuchElementException { | |
2290 if (typeStringDone()) throw new NoSuchElementException(); | |
2291 typeStringOffset += typeStringLength(); | |
2292 loadTypeString(); | |
2293 } | |
2294 | |
2295 public int typeStringLeaf() { | |
2296 return typeStringLeaf; | |
2297 } | |
2298 | |
2299 public int typeStringOffset() { | |
2300 return typeStringOffset; | |
2301 } | |
2302 | |
2303 /////////////////////////// | |
2304 // LF_MODIFIER accessors // | |
2305 /////////////////////////// | |
2306 | |
2307 public int getModifierIndex() { | |
2308 typeSeek(2); | |
2309 return readInt(); | |
2310 } | |
2311 | |
2312 public short getModifierAttribute() { | |
2313 typeSeek(6); | |
2314 return readShort(); | |
2315 } | |
2316 | |
2317 ////////////////////////// | |
2318 // LF_POINTER accessors // | |
2319 ////////////////////////// | |
2320 | |
2321 public int getPointerType() { | |
2322 typeSeek(2); | |
2323 return readInt(); | |
2324 } | |
2325 | |
2326 public int getPointerAttributes() { | |
2327 typeSeek(6); | |
2328 return readInt(); | |
2329 } | |
2330 | |
2331 public int getPointerBasedOnTypeIndex() { | |
2332 typeSeek(10); | |
2333 return readInt(); | |
2334 } | |
2335 | |
2336 public String getPointerBasedOnTypeName() { | |
2337 return readLengthPrefixedStringAt(14); | |
2338 } | |
2339 | |
2340 public int getPointerToMemberClass() { | |
2341 typeSeek(10); | |
2342 return readInt(); | |
2343 } | |
2344 | |
2345 public short getPointerToMemberFormat() { | |
2346 typeSeek(14); | |
2347 return readShort(); | |
2348 } | |
2349 | |
2350 //////////////////////// | |
2351 // LF_ARRAY accessors // | |
2352 //////////////////////// | |
2353 | |
2354 public int getArrayElementType() { | |
2355 typeSeek(2); | |
2356 return readInt(); | |
2357 } | |
2358 | |
2359 public int getArrayIndexType() { | |
2360 typeSeek(6); | |
2361 return readInt(); | |
2362 } | |
2363 | |
2364 public int getArrayLength() throws DebugVC50WrongNumericTypeException { | |
2365 return readIntNumericLeafAt(10); | |
2366 } | |
2367 | |
2368 public String getArrayName() { | |
2369 return readLengthPrefixedStringAt(10 + numericLeafLengthAt(10)); | |
2370 } | |
2371 | |
2372 ///////////////////////////////////////// | |
2373 // LF_CLASS and LF_STRUCTURE accessors // | |
2374 ///////////////////////////////////////// | |
2375 | |
2376 public short getClassCount() { | |
2377 typeSeek(2); | |
2378 return readShort(); | |
2379 } | |
2380 | |
2381 public short getClassProperty() { | |
2382 typeSeek(4); | |
2383 return readShort(); | |
2384 } | |
2385 | |
2386 public int getClassFieldList() { | |
2387 typeSeek(6); | |
2388 return readInt(); | |
2389 } | |
2390 | |
2391 public DebugVC50TypeIterator getClassFieldListIterator() { | |
2392 int index = unbiasTypeIndex(getClassFieldList()); | |
2393 int offset = parent.getTypeOffset(index); | |
2394 return new DebugVC50TypeIteratorImpl(parent, base, numTypes, index, offset); | |
2395 } | |
2396 | |
2397 public int getClassDerivationList() { | |
2398 typeSeek(10); | |
2399 return readInt(); | |
2400 } | |
2401 | |
2402 public int getClassVShape() { | |
2403 typeSeek(14); | |
2404 return readInt(); | |
2405 } | |
2406 | |
2407 public int getClassSize() throws DebugVC50WrongNumericTypeException { | |
2408 return readIntNumericLeafAt(18); | |
2409 } | |
2410 | |
2411 public String getClassName() { | |
2412 return readLengthPrefixedStringAt(18 + numericLeafLengthAt(18)); | |
2413 } | |
2414 | |
2415 //////////////////////// | |
2416 // LF_UNION accessors // | |
2417 //////////////////////// | |
2418 | |
2419 public short getUnionCount() { | |
2420 typeSeek(2); | |
2421 return readShort(); | |
2422 } | |
2423 | |
2424 public short getUnionProperty() { | |
2425 typeSeek(4); | |
2426 return readShort(); | |
2427 } | |
2428 | |
2429 public int getUnionFieldList() { | |
2430 typeSeek(6); | |
2431 return readInt(); | |
2432 } | |
2433 | |
2434 public DebugVC50TypeIterator getUnionFieldListIterator() { | |
2435 int index = unbiasTypeIndex(getUnionFieldList()); | |
2436 int offset = parent.getTypeOffset(index); | |
2437 return new DebugVC50TypeIteratorImpl(parent, base, numTypes, index, offset); | |
2438 } | |
2439 | |
2440 public int getUnionSize() throws DebugVC50WrongNumericTypeException { | |
2441 return readIntNumericLeafAt(10); | |
2442 } | |
2443 | |
2444 public String getUnionName() { | |
2445 return readLengthPrefixedStringAt(10 + numericLeafLengthAt(10)); | |
2446 } | |
2447 | |
2448 /////////////////////// | |
2449 // LF_ENUM accessors // | |
2450 /////////////////////// | |
2451 | |
2452 public short getEnumCount() { | |
2453 typeSeek(2); | |
2454 return readShort(); | |
2455 } | |
2456 | |
2457 public short getEnumProperty() { | |
2458 typeSeek(4); | |
2459 return readShort(); | |
2460 } | |
2461 | |
2462 public int getEnumType() { | |
2463 typeSeek(6); | |
2464 return readInt(); | |
2465 } | |
2466 | |
2467 public int getEnumFieldList() { | |
2468 typeSeek(10); | |
2469 return readInt(); | |
2470 } | |
2471 | |
2472 public DebugVC50TypeIterator getEnumFieldListIterator() { | |
2473 int index = unbiasTypeIndex(getEnumFieldList()); | |
2474 int offset = parent.getTypeOffset(index); | |
2475 return new DebugVC50TypeIteratorImpl(parent, base, numTypes, index, offset); | |
2476 } | |
2477 | |
2478 public String getEnumName() { | |
2479 return readLengthPrefixedStringAt(14); | |
2480 } | |
2481 | |
2482 //////////////////////////// | |
2483 // LF_PROCEDURE accessors // | |
2484 //////////////////////////// | |
2485 | |
2486 public int getProcedureReturnType() { | |
2487 typeSeek(2); | |
2488 return readInt(); | |
2489 } | |
2490 | |
2491 public byte getProcedureCallingConvention() { | |
2492 typeSeek(6); | |
2493 return readByte(); | |
2494 } | |
2495 | |
2496 public short getProcedureNumberOfParameters() { | |
2497 typeSeek(8); | |
2498 return readShort(); | |
2499 } | |
2500 | |
2501 public int getProcedureArgumentList() { | |
2502 typeSeek(10); | |
2503 return readInt(); | |
2504 } | |
2505 | |
2506 public DebugVC50TypeIterator getProcedureArgumentListIterator() { | |
2507 int index = unbiasTypeIndex(getProcedureArgumentList()); | |
2508 int offset = parent.getTypeOffset(index); | |
2509 return new DebugVC50TypeIteratorImpl(parent, base, numTypes, index, offset); | |
2510 } | |
2511 | |
2512 //////////////////////////// | |
2513 // LF_MFUNCTION accessors // | |
2514 //////////////////////////// | |
2515 | |
2516 public int getMFunctionReturnType() { | |
2517 typeSeek(2); | |
2518 return readInt(); | |
2519 } | |
2520 | |
2521 public int getMFunctionContainingClass() { | |
2522 typeSeek(6); | |
2523 return readInt(); | |
2524 } | |
2525 | |
2526 public int getMFunctionThis() { | |
2527 typeSeek(10); | |
2528 return readInt(); | |
2529 } | |
2530 | |
2531 public byte getMFunctionCallingConvention() { | |
2532 typeSeek(14); | |
2533 return readByte(); | |
2534 } | |
2535 | |
2536 public short getMFunctionNumberOfParameters() { | |
2537 typeSeek(16); | |
2538 return readShort(); | |
2539 } | |
2540 | |
2541 public int getMFunctionArgumentList() { | |
2542 typeSeek(18); | |
2543 return readInt(); | |
2544 } | |
2545 | |
2546 public DebugVC50TypeIterator getMFunctionArgumentListIterator() { | |
2547 int index = unbiasTypeIndex(getMFunctionArgumentList()); | |
2548 int offset = parent.getTypeOffset(index); | |
2549 return new DebugVC50TypeIteratorImpl(parent, base, numTypes, index, offset); | |
2550 } | |
2551 | |
2552 public int getMFunctionThisAdjust() { | |
2553 typeSeek(22); | |
2554 return readInt(); | |
2555 } | |
2556 | |
2557 ////////////////////////// | |
2558 // LF_VTSHAPE accessors // | |
2559 ////////////////////////// | |
2560 | |
2561 public short getVTShapeCount() { | |
2562 typeSeek(2); | |
2563 return readShort(); | |
2564 } | |
2565 | |
2566 public int getVTShapeDescriptor(int i) { | |
2567 typeSeek(4 + (i / 2)); | |
2568 int val = readByte() & 0xFF; | |
2569 if ((i % 2) != 0) { | |
2570 val = val >> 4; | |
2571 } | |
2572 return val; | |
2573 } | |
2574 | |
2575 ///////////////////////// | |
2576 // LF_BARRAY accessors // | |
2577 ///////////////////////// | |
2578 | |
2579 public int getBasicArrayType() { | |
2580 typeSeek(2); | |
2581 return readInt(); | |
2582 } | |
2583 | |
2584 //////////////////////// | |
2585 // LF_LABEL accessors // | |
2586 //////////////////////// | |
2587 | |
2588 public short getLabelAddressMode() { | |
2589 typeSeek(2); | |
2590 return readShort(); | |
2591 } | |
2592 | |
2593 /////////////////////////// | |
2594 // LF_DIMARRAY accessors // | |
2595 /////////////////////////// | |
2596 | |
2597 public int getDimArrayType() { | |
2598 typeSeek(2); | |
2599 return readInt(); | |
2600 } | |
2601 | |
2602 public int getDimArrayDimInfo() { | |
2603 typeSeek(6); | |
2604 return readInt(); | |
2605 } | |
2606 | |
2607 public String getDimArrayName() { | |
2608 return readLengthPrefixedStringAt(10); | |
2609 } | |
2610 | |
2611 ////////////////////////// | |
2612 // LF_VFTPATH accessors // | |
2613 ////////////////////////// | |
2614 | |
2615 public int getVFTPathCount() { | |
2616 typeSeek(2); | |
2617 return readInt(); | |
2618 } | |
2619 | |
2620 public int getVFTPathBase(int i) { | |
2621 typeSeek(6 + (4 * i)); | |
2622 return readInt(); | |
2623 } | |
2624 | |
2625 /////////////////////// | |
2626 // LF_SKIP accessors // | |
2627 /////////////////////// | |
2628 | |
2629 public int getSkipIndex() { | |
2630 typeSeek(2); | |
2631 return readInt(); | |
2632 } | |
2633 | |
2634 ////////////////////////// | |
2635 // LF_ARGLIST accessors // | |
2636 ////////////////////////// | |
2637 | |
2638 public int getArgListCount() { | |
2639 typeSeek(2); | |
2640 return readInt(); | |
2641 } | |
2642 | |
2643 public int getArgListType(int i) { | |
2644 typeSeek(6 + (4 * i)); | |
2645 return readInt(); | |
2646 } | |
2647 | |
2648 ///////////////////////// | |
2649 // LF_DEFARG accessors // | |
2650 ///////////////////////// | |
2651 | |
2652 public int getDefaultArgType() { | |
2653 typeSeek(2); | |
2654 return readInt(); | |
2655 } | |
2656 | |
2657 public String getDefaultArgExpression() { | |
2658 return readLengthPrefixedStringAt(6); | |
2659 } | |
2660 | |
2661 ////////////////////////// | |
2662 // LF_DERIVED accessors // | |
2663 ////////////////////////// | |
2664 | |
2665 public int getDerivedCount() { | |
2666 typeSeek(2); | |
2667 return readInt(); | |
2668 } | |
2669 | |
2670 public int getDerivedType(int i) { | |
2671 typeSeek(6); | |
2672 return readInt(); | |
2673 } | |
2674 | |
2675 /////////////////////////// | |
2676 // LF_BITFIELD accessors // | |
2677 /////////////////////////// | |
2678 | |
2679 public int getBitfieldFieldType() { | |
2680 typeSeek(2); | |
2681 return readInt(); | |
2682 } | |
2683 | |
2684 public byte getBitfieldLength() { | |
2685 typeSeek(6); | |
2686 return readByte(); | |
2687 } | |
2688 | |
2689 public byte getBitfieldPosition() { | |
2690 typeSeek(7); | |
2691 return readByte(); | |
2692 } | |
2693 | |
2694 //////////////////////// | |
2695 // LF_MLIST accessors // | |
2696 //////////////////////// | |
2697 | |
2698 public short getMListAttribute() { | |
2699 typeSeek(2); | |
2700 return readShort(); | |
2701 } | |
2702 | |
2703 public int getMListLength() { | |
2704 return (getLength() - 6 - (isMListIntroducingVirtual() ? 4 : 0)) / 4; | |
2705 } | |
2706 | |
2707 public int getMListType(int i) { | |
2708 typeSeek(6 + 4 * i); | |
2709 return readInt(); | |
2710 } | |
2711 | |
2712 public boolean isMListIntroducingVirtual() { | |
2713 return isIntroducingVirtual(getMListAttribute()); | |
2714 } | |
2715 | |
2716 public int getMListVtabOffset() { | |
2717 typeSeek(6 + 4 * getMListLength()); | |
2718 return readInt(); | |
2719 } | |
2720 | |
2721 ///////////////////////// | |
2722 // LF_REFSYM accessors // | |
2723 ///////////////////////// | |
2724 | |
2725 public DebugVC50SymbolIterator getRefSym() { | |
2726 typeSeek(2); | |
2727 int len = readShort() & 0xFFFF; | |
2728 return new DebugVC50SymbolIteratorImpl(typeStringOffset + 2, len); | |
2729 } | |
2730 | |
2731 ///////////////////////// | |
2732 // LF_BCLASS accessors // | |
2733 ///////////////////////// | |
2734 | |
2735 public short getBClassAttribute() { | |
2736 typeSeek(2); | |
2737 return readShort(); | |
2738 } | |
2739 | |
2740 public int getBClassType() { | |
2741 typeSeek(4); | |
2742 return readInt(); | |
2743 } | |
2744 | |
2745 public int getBClassOffset() throws DebugVC50WrongNumericTypeException { | |
2746 return readIntNumericLeafAt(8); | |
2747 } | |
2748 | |
2749 ////////////////////////// | |
2750 // LF_VBCLASS accessors // | |
2751 ////////////////////////// | |
2752 | |
2753 public short getVBClassAttribute() { | |
2754 typeSeek(2); | |
2755 return readShort(); | |
2756 } | |
2757 | |
2758 public int getVBClassBaseClassType() { | |
2759 typeSeek(4); | |
2760 return readInt(); | |
2761 } | |
2762 | |
2763 public int getVBClassVirtualBaseClassType() { | |
2764 typeSeek(8); | |
2765 return readInt(); | |
2766 } | |
2767 | |
2768 public int getVBClassVBPOff() throws DebugVC50WrongNumericTypeException { | |
2769 return readIntNumericLeafAt(12); | |
2770 } | |
2771 | |
2772 public int getVBClassVBOff() throws DebugVC50WrongNumericTypeException { | |
2773 return readIntNumericLeafAt(12 + numericLeafLengthAt(12)); | |
2774 } | |
2775 | |
2776 /////////////////////////// | |
2777 // LF_IVBCLASS accessors // | |
2778 /////////////////////////// | |
2779 | |
2780 public short getIVBClassAttribute() { | |
2781 typeSeek(2); | |
2782 return readShort(); | |
2783 } | |
2784 | |
2785 public int getIVBClassBType() { | |
2786 typeSeek(4); | |
2787 return readInt(); | |
2788 } | |
2789 | |
2790 public int getIVBClassVBPType() { | |
2791 typeSeek(8); | |
2792 return readInt(); | |
2793 } | |
2794 | |
2795 public int getIVBClassVBPOff() throws DebugVC50WrongNumericTypeException { | |
2796 return readIntNumericLeafAt(12); | |
2797 } | |
2798 | |
2799 public int getIVBClassVBOff() throws DebugVC50WrongNumericTypeException { | |
2800 return readIntNumericLeafAt(12 + numericLeafLengthAt(12)); | |
2801 } | |
2802 | |
2803 //////////////////////////// | |
2804 // LF_ENUMERATE accessors // | |
2805 //////////////////////////// | |
2806 | |
2807 public short getEnumerateAttribute() { | |
2808 typeSeek(2); | |
2809 return readShort(); | |
2810 } | |
2811 | |
2812 public long getEnumerateValue() { | |
2813 return readIntNumericLeafAt(4); | |
2814 } | |
2815 | |
2816 public String getEnumerateName() { | |
2817 return readLengthPrefixedStringAt(4 + numericLeafLengthAt(4)); | |
2818 } | |
2819 | |
2820 //////////////////////////// | |
2821 // LF_FRIENDFCN accessors // | |
2822 //////////////////////////// | |
2823 | |
2824 public int getFriendFcnType() { | |
2825 typeSeek(4); | |
2826 return readInt(); | |
2827 } | |
2828 | |
2829 public String getFriendFcnName() { | |
2830 return readLengthPrefixedStringAt(8); | |
2831 } | |
2832 | |
2833 //////////////////////// | |
2834 // LF_INDEX accessors // | |
2835 //////////////////////// | |
2836 | |
2837 public int getIndexValue() { | |
2838 typeSeek(4); | |
2839 return readInt(); | |
2840 } | |
2841 | |
2842 public DebugVC50TypeIterator getIndexIterator() { | |
2843 int index = unbiasTypeIndex(getIndexValue()); | |
2844 int offset = parent.getTypeOffset(index); | |
2845 return new DebugVC50TypeIteratorImpl(parent, base, numTypes, index, offset); | |
2846 } | |
2847 | |
2848 ///////////////////////// | |
2849 // LF_MEMBER accessors // | |
2850 ///////////////////////// | |
2851 | |
2852 public short getMemberAttribute() { | |
2853 typeSeek(2); | |
2854 return readShort(); | |
2855 } | |
2856 | |
2857 public int getMemberType() { | |
2858 typeSeek(4); | |
2859 return readInt(); | |
2860 } | |
2861 | |
2862 public int getMemberOffset() throws DebugVC50WrongNumericTypeException { | |
2863 return readIntNumericLeafAt(8); | |
2864 } | |
2865 | |
2866 public String getMemberName() { | |
2867 return readLengthPrefixedStringAt(8 + numericLeafLengthAt(8)); | |
2868 } | |
2869 | |
2870 /////////////////////////// | |
2871 // LF_STMEMBER accessors // | |
2872 /////////////////////////// | |
2873 | |
2874 public short getStaticAttribute() { | |
2875 typeSeek(2); | |
2876 return readShort(); | |
2877 } | |
2878 | |
2879 public int getStaticType() { | |
2880 typeSeek(4); | |
2881 return readInt(); | |
2882 } | |
2883 | |
2884 public String getStaticName() { | |
2885 return readLengthPrefixedStringAt(8); | |
2886 } | |
2887 | |
2888 ///////////////////////// | |
2889 // LF_METHOD accessors // | |
2890 ///////////////////////// | |
2891 | |
2892 public short getMethodCount() { | |
2893 typeSeek(2); | |
2894 return readShort(); | |
2895 } | |
2896 | |
2897 public int getMethodList() { | |
2898 typeSeek(4); | |
2899 return readInt(); | |
2900 } | |
2901 | |
2902 public String getMethodName() { | |
2903 return readLengthPrefixedStringAt(8); | |
2904 } | |
2905 | |
2906 ///////////////////////////// | |
2907 // LF_NESTEDTYPE accessors // | |
2908 ///////////////////////////// | |
2909 | |
2910 public int getNestedType() { | |
2911 typeSeek(4); | |
2912 return readInt(); | |
2913 } | |
2914 | |
2915 public String getNestedName() { | |
2916 return readLengthPrefixedStringAt(8); | |
2917 } | |
2918 | |
2919 /////////////////////////// | |
2920 // LF_VFUNCTAB accessors // | |
2921 /////////////////////////// | |
2922 | |
2923 public int getVFuncTabType() { | |
2924 typeSeek(4); | |
2925 return readInt(); | |
2926 } | |
2927 | |
2928 //////////////////////////// | |
2929 // LF_FRIENDCLS accessors // | |
2930 //////////////////////////// | |
2931 | |
2932 public int getFriendClsType() { | |
2933 typeSeek(4); | |
2934 return readInt(); | |
2935 } | |
2936 | |
2937 //////////////////////////// | |
2938 // LF_ONEMETHOD accessors // | |
2939 //////////////////////////// | |
2940 | |
2941 public short getOneMethodAttribute() { | |
2942 typeSeek(2); | |
2943 return readShort(); | |
2944 } | |
2945 | |
2946 public int getOneMethodType() { | |
2947 typeSeek(4); | |
2948 return readInt(); | |
2949 } | |
2950 | |
2951 public boolean isOneMethodIntroducingVirtual() { | |
2952 return isIntroducingVirtual(getOneMethodAttribute()); | |
2953 } | |
2954 | |
2955 public int getOneMethodVBaseOff() { | |
2956 typeSeek(8); | |
2957 return readInt(); | |
2958 } | |
2959 | |
2960 public String getOneMethodName() { | |
2961 int baseLen = 8 + (isOneMethodIntroducingVirtual() ? 4 : 0); | |
2962 return readLengthPrefixedStringAt(baseLen); | |
2963 } | |
2964 | |
2965 /////////////////////////// | |
2966 // LF_VFUNCOFF accessors // | |
2967 /////////////////////////// | |
2968 | |
2969 public int getVFuncOffType() { | |
2970 typeSeek(4); | |
2971 return readInt(); | |
2972 } | |
2973 | |
2974 public int getVFuncOffOffset() { | |
2975 typeSeek(8); | |
2976 return readInt(); | |
2977 } | |
2978 | |
2979 /////////////////////////////// | |
2980 // LF_NESTEDTYPEEX accessors // | |
2981 /////////////////////////////// | |
2982 | |
2983 public short getNestedExAttribute() { | |
2984 typeSeek(2); | |
2985 return readShort(); | |
2986 } | |
2987 | |
2988 public int getNestedExType() { | |
2989 typeSeek(4); | |
2990 return readInt(); | |
2991 } | |
2992 | |
2993 public String getNestedExName() { | |
2994 return readLengthPrefixedStringAt(8); | |
2995 } | |
2996 | |
2997 /////////////////////////////// | |
2998 // LF_MEMBERMODIFY accessors // | |
2999 /////////////////////////////// | |
3000 | |
3001 public short getMemberModifyAttribute() { | |
3002 typeSeek(2); | |
3003 return readShort(); | |
3004 } | |
3005 | |
3006 public int getMemberModifyType() { | |
3007 typeSeek(4); | |
3008 return readInt(); | |
3009 } | |
3010 | |
3011 public String getMemberModifyName() { | |
3012 return readLengthPrefixedStringAt(8); | |
3013 } | |
3014 | |
3015 //////////////////////////// | |
3016 // Numeric Leaf accessors // | |
3017 //////////////////////////// | |
3018 | |
3019 public short getNumericTypeAt(int byteOffset) { | |
3020 typeSeek(byteOffset); | |
3021 return readShort(); | |
3022 } | |
3023 | |
3024 public int getNumericLengthAt(int byteOffset) | |
3025 throws DebugVC50WrongNumericTypeException { | |
3026 return numericLeafLengthAt(byteOffset); | |
3027 } | |
3028 | |
3029 public int getNumericIntAt(int byteOffset) | |
3030 throws DebugVC50WrongNumericTypeException { | |
3031 return readIntNumericLeafAt(byteOffset); | |
3032 } | |
3033 | |
3034 public long getNumericLongAt(int byteOffset) | |
3035 throws DebugVC50WrongNumericTypeException { | |
3036 // FIXME | |
3037 throw new RuntimeException("Unimplemented"); | |
3038 } | |
3039 | |
3040 public float getNumericFloatAt(int byteOffset) | |
3041 throws DebugVC50WrongNumericTypeException { | |
3042 // FIXME | |
3043 throw new RuntimeException("Unimplemented"); | |
3044 } | |
3045 | |
3046 public double getNumericDoubleAt(int byteOffset) | |
3047 throws DebugVC50WrongNumericTypeException { | |
3048 // FIXME | |
3049 throw new RuntimeException("Unimplemented"); | |
3050 } | |
3051 | |
3052 public byte[] getNumericDataAt(int byteOffset) | |
3053 throws DebugVC50WrongNumericTypeException { | |
3054 // FIXME | |
3055 throw new RuntimeException("Unimplemented"); | |
3056 } | |
3057 | |
3058 //---------------------------------------------------------------------- | |
3059 // Internals only below this point | |
3060 // | |
3061 | |
3062 private void loadTypeRecord() { | |
3063 seek(typeRecordOffset); | |
3064 typeRecordSize = readShort() & 0xFFFF; | |
3065 typeStringOffset = typeRecordOffset + 2; | |
3066 loadTypeString(); | |
3067 } | |
3068 | |
3069 private void loadTypeString() { | |
3070 seek(typeStringOffset); | |
3071 int lo = readByte() & 0xFF; | |
3072 // See if it is one of the single-byte leaves | |
3073 if (lo >= LF_PAD0) { | |
3074 typeStringLeaf = lo; | |
3075 } else { | |
3076 int hi = readByte() & 0xFF; | |
3077 typeStringLeaf = (hi << 8) | lo; | |
3078 } | |
3079 } | |
3080 | |
3081 private void typeSeek(int offset) { | |
3082 seek(typeStringOffset + offset); | |
3083 } | |
3084 | |
3085 private int typeStringLength() { | |
3086 // LF_PAD | |
3087 if (typeStringLeaf >= 0xF0 && typeStringLeaf <= 0xFF) { | |
3088 return (typeStringLeaf - 0xF0); | |
3089 } | |
3090 | |
3091 switch (typeStringLeaf) { | |
3092 | |
3093 // Leaf indices for type records that can be referenced | |
3094 // from symbols: | |
3095 case LF_MODIFIER: return 8; | |
3096 case LF_POINTER: { | |
3097 int extraLen = 0; | |
3098 int attr = (getPointerAttributes() & POINTER_PTRTYPE_MASK) >> POINTER_PTRTYPE_SHIFT; | |
3099 int mode = (getPointerAttributes() & POINTER_PTRMODE_MASK) >> POINTER_PTRMODE_SHIFT; | |
3100 if (attr == POINTER_PTRTYPE_BASED_ON_TYPE) { | |
3101 extraLen = 4 + numericLeafLengthAt(typeStringOffset + 14); | |
3102 } else if (mode == POINTER_PTRMODE_PTR_TO_DATA_MEMBER || | |
3103 mode == POINTER_PTRMODE_PTR_TO_METHOD) { | |
3104 extraLen = 6; | |
3105 } | |
3106 return 10 + extraLen; | |
3107 } | |
3108 case LF_ARRAY: { | |
3109 int temp = 10 + numericLeafLengthAt(10); | |
3110 return temp + lengthPrefixedStringLengthAt(temp); | |
3111 } | |
3112 case LF_CLASS: | |
3113 case LF_STRUCTURE: { | |
3114 int temp = 18 + numericLeafLengthAt(18); | |
3115 return temp + lengthPrefixedStringLengthAt(temp); | |
3116 } | |
3117 case LF_UNION: { | |
3118 int temp = 10 + numericLeafLengthAt(10); | |
3119 return temp + lengthPrefixedStringLengthAt(temp); | |
3120 } | |
3121 case LF_ENUM: { | |
3122 return 14 + lengthPrefixedStringLengthAt(14); | |
3123 } | |
3124 case LF_PROCEDURE: return 14; | |
3125 case LF_MFUNCTION: return 26; | |
3126 case LF_VTSHAPE: return 4 + ((getVTShapeCount() + 1) / 2); | |
3127 case LF_COBOL0: | |
3128 case LF_COBOL1: throw new COFFException("COBOL symbols unimplemented"); | |
3129 case LF_BARRAY: return 6; | |
3130 case LF_LABEL: return 4; | |
3131 case LF_NULL: return 2; | |
3132 case LF_NOTTRAN: return 2; | |
3133 case LF_DIMARRAY: return 10 + lengthPrefixedStringLengthAt(10); | |
3134 case LF_VFTPATH: return 6 + 4 * getVFTPathCount(); | |
3135 case LF_PRECOMP: return 14 + lengthPrefixedStringLengthAt(14); | |
3136 case LF_ENDPRECOMP: return 6; | |
3137 case LF_OEM: throw new COFFException("OEM symbols unimplemented"); | |
3138 case LF_TYPESERVER: return 10 + lengthPrefixedStringLengthAt(10); | |
3139 | |
3140 case LF_SKIP: return 6 + numericLeafLengthAt(6); | |
3141 case LF_ARGLIST: return 6 + 4 * getArgListCount(); | |
3142 case LF_DEFARG: return 6 + lengthPrefixedStringLengthAt(6); | |
3143 // case LF_FIELDLIST: throw new COFFException("Should not see LF_FIELDLIST leaf"); | |
3144 case LF_FIELDLIST: return 2; | |
3145 case LF_DERIVED: return 6 + 4 * getDerivedCount(); | |
3146 case LF_BITFIELD: return 8; | |
3147 case LF_METHODLIST: { | |
3148 return 6 + 4 * getMListLength() + (isMListIntroducingVirtual() ? 4 : 0); | |
3149 } | |
3150 case LF_DIMCONU: | |
3151 case LF_DIMCONLU: | |
3152 case LF_DIMVARU: | |
3153 case LF_DIMVARLU: throw new COFFException("LF_DIMCONU, LF_DIMCONLU, LF_DIMVARU, and LF_DIMVARLU unsupported"); | |
3154 case LF_REFSYM: { | |
3155 seek(typeStringOffset + 2); | |
3156 return 4 + readShort(); | |
3157 } | |
3158 | |
3159 case LF_BCLASS: return 8 + numericLeafLengthAt(8); | |
3160 case LF_VBCLASS: | |
3161 case LF_IVBCLASS: { | |
3162 int temp = 12 + numericLeafLengthAt(12); | |
3163 return temp + numericLeafLengthAt(temp); | |
3164 } | |
3165 case LF_ENUMERATE: { | |
3166 int temp = 4 + numericLeafLengthAt(4); | |
3167 return temp + lengthPrefixedStringLengthAt(temp); | |
3168 } | |
3169 case LF_FRIENDFCN: return 8 + lengthPrefixedStringLengthAt(8); | |
3170 case LF_INDEX: return 8; | |
3171 case LF_MEMBER: { | |
3172 int temp = 8 + numericLeafLengthAt(8); | |
3173 return temp + lengthPrefixedStringLengthAt(temp); | |
3174 } | |
3175 case LF_STMEMBER: return 8 + lengthPrefixedStringLengthAt(8); | |
3176 case LF_METHOD: return 8 + lengthPrefixedStringLengthAt(8); | |
3177 case LF_NESTTYPE: return 8 + lengthPrefixedStringLengthAt(8); | |
3178 case LF_VFUNCTAB: return 8; | |
3179 case LF_FRIENDCLS: return 8; | |
3180 case LF_ONEMETHOD: { | |
3181 int baseLen = 8 + (isOneMethodIntroducingVirtual() ? 4 : 0); | |
3182 return baseLen + lengthPrefixedStringLengthAt(baseLen); | |
3183 } | |
3184 case LF_VFUNCOFF: return 12; | |
3185 case LF_NESTTYPEEX: return 8 + lengthPrefixedStringLengthAt(8); | |
3186 case LF_MEMBERMODIFY: return 8 + lengthPrefixedStringLengthAt(8); | |
3187 | |
3188 // Should not encounter numeric leaves with this routine | |
3189 case LF_CHAR: | |
3190 case LF_SHORT: | |
3191 case LF_USHORT: | |
3192 case LF_LONG: | |
3193 case LF_ULONG: | |
3194 case LF_REAL32: | |
3195 case LF_REAL64: | |
3196 case LF_REAL80: | |
3197 case LF_REAL128: | |
3198 case LF_QUADWORD: | |
3199 case LF_UQUADWORD: | |
3200 case LF_REAL48: | |
3201 case LF_COMPLEX32: | |
3202 case LF_COMPLEX64: | |
3203 case LF_COMPLEX80: | |
3204 case LF_COMPLEX128: | |
3205 case LF_VARSTRING: throw new RuntimeException("Unexpected numeric leaf " + typeStringLeaf + | |
3206 "in type string"); | |
3207 default: | |
3208 throw new COFFException("Unrecognized leaf " + typeStringLeaf + " in type string at offset " + | |
3209 typeStringOffset); | |
3210 } | |
3211 } | |
3212 | |
3213 private boolean isIntroducingVirtual(int mprop) { | |
3214 int masked = mprop & MEMATTR_MPROP_MASK; | |
3215 return ((masked == MEMATTR_MPROP_INTRODUCING_VIRTUAL) || | |
3216 (masked == MEMATTR_MPROP_PURE_INTRODUCING_VIRTUAL)); | |
3217 } | |
3218 | |
3219 private int numericLeafLengthAt(int offset) { | |
3220 return DebugVC50Impl.this.numericLeafLengthAt(typeStringOffset + offset); | |
3221 } | |
3222 | |
3223 private int readIntNumericLeafAt(int offset) { | |
3224 return DebugVC50Impl.this.readIntNumericLeafAt(typeStringOffset + offset); | |
3225 } | |
3226 | |
3227 private int lengthPrefixedStringLengthAt(int offset) { | |
3228 return DebugVC50Impl.this.lengthPrefixedStringLengthAt(typeStringOffset + offset); | |
3229 } | |
3230 | |
3231 private String readLengthPrefixedStringAt(int offset) { | |
3232 return DebugVC50Impl.this.readLengthPrefixedStringAt(typeStringOffset + offset); | |
3233 } | |
3234 } | |
3235 | |
3236 private int numericLeafLengthAt(int absoluteOffset) throws DebugVC50WrongNumericTypeException { | |
3237 seek(absoluteOffset); | |
3238 int leaf = readShort() & 0xFFFF; | |
3239 if (leaf < 0x8000) return 2; | |
3240 switch (leaf) { | |
3241 case LF_CHAR: return 3; | |
3242 case LF_SHORT: | |
3243 case LF_USHORT: return 4; | |
3244 case LF_LONG: | |
3245 case LF_ULONG: return 6; | |
3246 case LF_REAL32: return 6; | |
3247 case LF_REAL64: return 10; | |
3248 case LF_REAL80: return 12; | |
3249 case LF_REAL128: return 18; | |
3250 case LF_QUADWORD: | |
3251 case LF_UQUADWORD: return 18; | |
3252 case LF_REAL48: return 8; | |
3253 case LF_COMPLEX32: return 10; | |
3254 case LF_COMPLEX64: return 18; | |
3255 case LF_COMPLEX80: return 26; | |
3256 case LF_COMPLEX128: return 66; | |
3257 // FIXME: figure out format of variable-length strings | |
3258 case LF_VARSTRING: return 4 + readIntNumericLeafAt(absoluteOffset + 2); | |
3259 | |
3260 default: | |
3261 throw new DebugVC50WrongNumericTypeException("Illegal numeric leaf index " + leaf + | |
3262 " at offset " + absoluteOffset); | |
3263 } | |
3264 } | |
3265 | |
3266 private int readIntNumericLeafAt(int absoluteOffset) throws DebugVC50WrongNumericTypeException { | |
3267 seek(absoluteOffset); | |
3268 int leaf = readShort() & 0xFFFF; | |
3269 if (leaf < 0x8000) return leaf; | |
3270 switch (leaf) { | |
3271 case LF_CHAR: return readByte() & 0xFF; | |
3272 case LF_SHORT: | |
3273 case LF_USHORT: return readShort() & 0xFFFF; | |
3274 case LF_LONG: | |
3275 case LF_ULONG: return readInt(); | |
3276 | |
3277 default: | |
3278 throw new DebugVC50WrongNumericTypeException("Illegal numeric leaf index " + leaf); | |
3279 } | |
3280 } | |
3281 | |
3282 private long readLongNumericLeafAt(int absoluteOffset) throws DebugVC50WrongNumericTypeException { | |
3283 seek(absoluteOffset); | |
3284 int leaf = readShort() & 0xFFFF; | |
3285 if (leaf < 0x8000) return leaf; | |
3286 switch (leaf) { | |
3287 case LF_CHAR: return readByte() & 0xFF; | |
3288 case LF_SHORT: | |
3289 case LF_USHORT: return readShort() & 0xFFFF; | |
3290 case LF_LONG: | |
3291 case LF_ULONG: return readInt() & 0xFFFFFFFF; | |
3292 case LF_QUADWORD: | |
3293 case LF_UQUADWORD: return readLong(); | |
3294 | |
3295 default: | |
3296 throw new DebugVC50WrongNumericTypeException("Illegal numeric leaf index " + leaf); | |
3297 } | |
3298 } | |
3299 | |
3300 private float readFloatNumericLeafAt(int absoluteOffset) throws DebugVC50WrongNumericTypeException { | |
3301 seek(absoluteOffset); | |
3302 int leaf = readShort() & 0xFFFF; | |
3303 if (leaf != LF_REAL32) { | |
3304 throw new DebugVC50WrongNumericTypeException("Illegal numeric leaf index " + leaf); | |
3305 } | |
3306 return readFloat(); | |
3307 } | |
3308 | |
3309 private double readDoubleNumericLeafAt(int absoluteOffset) throws DebugVC50WrongNumericTypeException { | |
3310 seek(absoluteOffset); | |
3311 int leaf = readShort() & 0xFFFF; | |
3312 if (leaf != LF_REAL64) { | |
3313 throw new DebugVC50WrongNumericTypeException("Illegal numeric leaf index " + leaf); | |
3314 } | |
3315 return readDouble(); | |
3316 } | |
3317 | |
3318 private int lengthPrefixedStringLengthAt(int absoluteOffset) { | |
3319 // NOTE: the format of length-prefixed strings is not well | |
3320 // specified. There is a LF_VARSTRING numeric leaf (the | |
3321 // format of which is also not specified), but it seems that | |
3322 // most length-prefixed strings are comprised of a single | |
3323 // byte length followed by that many bytes of data. | |
3324 seek(absoluteOffset); | |
3325 int len = readByte() & 0xFF; | |
3326 return 1 + len; | |
3327 } | |
3328 | |
3329 private String readLengthPrefixedStringAt(int absoluteOffset) { | |
3330 // NOTE: it isn't clear whether LF_VARSTRING numeric leaves | |
3331 // ever show up, or in general what happens when the length | |
3332 // of the string is > 255 (FIXME) | |
3333 seek(absoluteOffset); | |
3334 int len = readByte() & 0xFF; | |
3335 byte[] res = new byte[len]; | |
3336 int numRead = readBytes(res); | |
3337 if (numRead != len) { | |
3338 throw new COFFException("Error reading length prefixed string in symbol at offset " + | |
3339 absoluteOffset); | |
3340 } | |
3341 try { | |
3342 return new String(res, US_ASCII); | |
3343 } catch (UnsupportedEncodingException e) { | |
3344 throw new COFFException(e); | |
3345 } | |
3346 } | |
3347 | |
3348 private int unbiasTypeIndex(int index) { | |
3349 return index - 0x1000; | |
3350 } | |
3351 | |
3352 private int biasTypeIndex(int index) { | |
3353 return index + 0x1000; | |
3354 } | |
3355 } // Class DebugVC50Impl | |
3356 | |
3357 class SectionHeaderImpl implements SectionHeader { | |
3358 private String name; | |
3359 private int virtualSize; | |
3360 private int virtualAddress; | |
3361 private int sizeOfRawData; | |
3362 private int pointerToRawData; | |
3363 private int pointerToRelocations; | |
3364 private int pointerToLineNumbers; | |
3365 private short numberOfRelocations; | |
3366 private short numberOfLineNumbers; | |
3367 private int characteristics; | |
3368 private MemoizedObject[] relocations; | |
3369 private MemoizedObject[] lineNumbers; | |
3370 | |
3371 public SectionHeaderImpl(int offset) throws COFFException { | |
3372 seek(offset); | |
3373 | |
3374 // FIXME: compute name lazily | |
3375 | |
3376 // Read name | |
3377 byte[] tmpName = new byte[8]; | |
3378 int numRead = readBytes(tmpName); | |
3379 if (numRead != 8) { | |
3380 throw new COFFException("Error reading name of section header at offset " + offset); | |
3381 } | |
3382 if (tmpName[0] == (byte) '/') { | |
3383 // Long name; must find real value in string table | |
3384 int index = 0; | |
3385 try { | |
3386 index = Integer.parseInt(new String(tmpName, 1, tmpName.length - 1, US_ASCII)); | |
3387 } catch (NumberFormatException e) { | |
3388 throw new COFFException("Error parsing string table index of name of section header " + | |
3389 "at offset " + offset); | |
3390 } catch (UnsupportedEncodingException e) { | |
3391 throw new COFFException(e); | |
3392 } | |
3393 // Look up in string table | |
2072
d6cd0d55d0b5
6987812: 2/3 SAJDI: "gHotSpotVMTypes was not initialized properly in the remote process"
dcubed
parents:
1552
diff
changeset
|
3394 // FIXME: this index value is assumed to be in the valid range |
0 | 3395 name = getStringTable().get(index); |
3396 } else { | |
3397 try { | |
2072
d6cd0d55d0b5
6987812: 2/3 SAJDI: "gHotSpotVMTypes was not initialized properly in the remote process"
dcubed
parents:
1552
diff
changeset
|
3398 int length = 0; |
d6cd0d55d0b5
6987812: 2/3 SAJDI: "gHotSpotVMTypes was not initialized properly in the remote process"
dcubed
parents:
1552
diff
changeset
|
3399 // find last non-NULL |
d6cd0d55d0b5
6987812: 2/3 SAJDI: "gHotSpotVMTypes was not initialized properly in the remote process"
dcubed
parents:
1552
diff
changeset
|
3400 for (; length < tmpName.length && tmpName[length] != '\0';) { |
d6cd0d55d0b5
6987812: 2/3 SAJDI: "gHotSpotVMTypes was not initialized properly in the remote process"
dcubed
parents:
1552
diff
changeset
|
3401 length++; |
d6cd0d55d0b5
6987812: 2/3 SAJDI: "gHotSpotVMTypes was not initialized properly in the remote process"
dcubed
parents:
1552
diff
changeset
|
3402 } |
d6cd0d55d0b5
6987812: 2/3 SAJDI: "gHotSpotVMTypes was not initialized properly in the remote process"
dcubed
parents:
1552
diff
changeset
|
3403 // don't include NULL chars in returned name String |
d6cd0d55d0b5
6987812: 2/3 SAJDI: "gHotSpotVMTypes was not initialized properly in the remote process"
dcubed
parents:
1552
diff
changeset
|
3404 name = new String(tmpName, 0, length, US_ASCII); |
0 | 3405 } catch (UnsupportedEncodingException e) { |
3406 throw new COFFException(e); | |
3407 } | |
3408 } | |
3409 virtualSize = readInt(); | |
3410 virtualAddress = readInt(); | |
3411 sizeOfRawData = readInt(); | |
3412 pointerToRawData = readInt(); | |
3413 pointerToRelocations = readInt(); | |
3414 pointerToLineNumbers = readInt(); | |
3415 numberOfRelocations = readShort(); | |
3416 numberOfLineNumbers = readShort(); | |
3417 characteristics = readInt(); | |
3418 | |
3419 // Set up relocations | |
3420 relocations = new MemoizedObject[numberOfRelocations]; | |
3421 for (int i = 0; i < numberOfRelocations; i++) { | |
3422 final int relocOffset = pointerToRelocations + i * RELOCATION_SIZE; | |
3423 relocations[i] = new MemoizedObject() { | |
3424 public Object computeValue() { | |
3425 return new COFFRelocationImpl(relocOffset); | |
3426 } | |
3427 }; | |
3428 } | |
3429 | |
3430 // Set up line numbers | |
3431 lineNumbers = new MemoizedObject[numberOfLineNumbers]; | |
3432 for (int i = 0; i < numberOfLineNumbers; i++) { | |
3433 final int lineNoOffset = pointerToLineNumbers + i * LINE_NUMBER_SIZE; | |
3434 lineNumbers[i] = new MemoizedObject() { | |
3435 public Object computeValue() { | |
3436 return new COFFLineNumberImpl(lineNoOffset); | |
3437 } | |
3438 }; | |
3439 } | |
3440 } | |
3441 | |
3442 public String getName() { return name; } | |
3443 public int getSize() { return virtualSize; } | |
3444 public int getVirtualAddress() { return virtualAddress; } | |
3445 public int getSizeOfRawData() { return sizeOfRawData; } | |
3446 public int getPointerToRawData() { return pointerToRawData; } | |
3447 public int getPointerToRelocations() { return pointerToRelocations; } | |
3448 public int getPointerToLineNumbers() { return pointerToLineNumbers; } | |
3449 public short getNumberOfRelocations() { return numberOfRelocations; } | |
3450 public short getNumberOfLineNumbers() { return numberOfLineNumbers; } | |
3451 public int getSectionFlags() { return characteristics; } | |
3452 public boolean hasSectionFlag(int flag ) { | |
3453 return ((characteristics & flag) != 0); | |
3454 } | |
3455 public COFFRelocation getCOFFRelocation(int index) { | |
3456 return (COFFRelocation) relocations[index].getValue(); | |
3457 } | |
3458 public COFFLineNumber getCOFFLineNumber(int index) { | |
3459 return (COFFLineNumber) lineNumbers[index]; | |
3460 } | |
3461 } | |
3462 | |
3463 class COFFSymbolImpl implements COFFSymbol, COFFSymbolConstants { | |
3464 private int offset; | |
3465 private String name; | |
3466 private int value; | |
3467 private short sectionNumber; | |
3468 private short type; | |
3469 private byte storageClass; | |
3470 private byte numberOfAuxSymbols; | |
3471 private MemoizedObject auxFunctionDefinitionRecord = new MemoizedObject() { | |
3472 public Object computeValue() { | |
3473 return new AuxFunctionDefinitionRecordImpl(offset + SYMBOL_SIZE); | |
3474 } | |
3475 }; | |
3476 private MemoizedObject auxBfEfRecord = new MemoizedObject() { | |
3477 public Object computeValue() { | |
3478 return new AuxBfEfRecordImpl(offset + SYMBOL_SIZE); | |
3479 } | |
3480 }; | |
3481 private MemoizedObject auxWeakExternalRecord = new MemoizedObject() { | |
3482 public Object computeValue() { | |
3483 return new AuxWeakExternalRecordImpl(offset + SYMBOL_SIZE); | |
3484 } | |
3485 }; | |
3486 private MemoizedObject auxFileRecord = new MemoizedObject() { | |
3487 public Object computeValue() { | |
3488 return new AuxFileRecordImpl(offset + SYMBOL_SIZE); | |
3489 } | |
3490 }; | |
3491 private MemoizedObject auxSectionDefinitionsRecord = new MemoizedObject() { | |
3492 public Object computeValue() { | |
3493 return new AuxSectionDefinitionsRecordImpl(offset + SYMBOL_SIZE); | |
3494 } | |
3495 }; | |
3496 | |
3497 public COFFSymbolImpl(int offset) throws COFFException { | |
3498 this.offset = offset; | |
3499 seek(offset); | |
3500 | |
3501 // Parse name | |
3502 byte[] tmpName = new byte[8]; | |
3503 int numRead = readBytes(tmpName); | |
3504 if (numRead != 8) { | |
3505 throw new COFFException("Error reading name of symbol at offset " + offset); | |
3506 } | |
3507 if ((tmpName[0] == 0) && | |
3508 (tmpName[1] == 0) && | |
3509 (tmpName[2] == 0) && | |
3510 (tmpName[3] == 0)) { | |
3511 // It's an offset into the string table. | |
3512 // FIXME: not sure about byte ordering... | |
3513 int stringOffset = (tmpName[4] << 24 | | |
3514 tmpName[5] << 16 | | |
3515 tmpName[6] << 8 | | |
3516 tmpName[7]); | |
2072
d6cd0d55d0b5
6987812: 2/3 SAJDI: "gHotSpotVMTypes was not initialized properly in the remote process"
dcubed
parents:
1552
diff
changeset
|
3517 // FIXME: stringOffset is assumed to be in the valid range |
0 | 3518 name = getStringTable().getAtOffset(stringOffset); |
3519 } | |
3520 | |
3521 value = readInt(); | |
3522 sectionNumber = readShort(); | |
3523 type = readShort(); | |
3524 storageClass = readByte(); | |
3525 numberOfAuxSymbols = readByte(); | |
3526 } | |
3527 | |
3528 public int getOffset() { return offset; } | |
3529 public String getName() { return name; } | |
3530 public int getValue() { return value; } | |
3531 public short getSectionNumber() { return sectionNumber; } | |
3532 public short getType() { return type; } | |
3533 public byte getStorageClass() { return storageClass; } | |
3534 public byte getNumberOfAuxSymbols() { return numberOfAuxSymbols; } | |
3535 public boolean isFunctionDefinition() { | |
3536 return ((getStorageClass() == IMAGE_SYM_CLASS_EXTERNAL) && | |
3537 ((getType() >>> 8) == IMAGE_SYM_DTYPE_FUNCTION) && | |
3538 (getSectionNumber() > 0)); | |
3539 } | |
3540 public AuxFunctionDefinitionRecord getAuxFunctionDefinitionRecord() { | |
3541 return (AuxFunctionDefinitionRecord) auxFunctionDefinitionRecord.getValue(); | |
3542 } | |
3543 public boolean isBfOrEfSymbol() { | |
3544 return ((getName().equals(".bf") || getName().equals(".ef")) && | |
3545 (getStorageClass() == IMAGE_SYM_CLASS_FUNCTION)); | |
3546 } | |
3547 public AuxBfEfRecord getAuxBfEfRecord() { | |
3548 return (AuxBfEfRecord) auxBfEfRecord.getValue(); | |
3549 } | |
3550 public boolean isWeakExternal() { | |
3551 return ((getStorageClass() == IMAGE_SYM_CLASS_EXTERNAL) && | |
3552 (getSectionNumber() == IMAGE_SYM_UNDEFINED) && | |
3553 (getValue() == 0)); | |
3554 } | |
3555 public AuxWeakExternalRecord getAuxWeakExternalRecord() { | |
3556 return (AuxWeakExternalRecord) auxWeakExternalRecord.getValue(); | |
3557 } | |
3558 public boolean isFile() { | |
3559 return ((getName().equals(".file")) && | |
3560 (getStorageClass() == IMAGE_SYM_CLASS_FILE)); | |
3561 } | |
3562 public AuxFileRecord getAuxFileRecord() { | |
3563 return (AuxFileRecord) auxFileRecord.getValue(); | |
3564 } | |
3565 public boolean isSectionDefinition() { | |
3566 // FIXME: not sure how to ensure that symbol name is the | |
3567 // name of a section. | |
3568 return ((getName().charAt(0) == '.') && | |
3569 (getStorageClass() == IMAGE_SYM_CLASS_STATIC)); | |
3570 } | |
3571 public AuxSectionDefinitionsRecord getAuxSectionDefinitionsRecord() { | |
3572 return (AuxSectionDefinitionsRecord) auxSectionDefinitionsRecord.getValue(); | |
3573 } | |
3574 } | |
3575 | |
3576 class AuxFunctionDefinitionRecordImpl implements AuxFunctionDefinitionRecord { | |
3577 private int tagIndex; | |
3578 private int totalSize; | |
3579 private int pointerToLineNumber; | |
3580 private int pointerToNextFunction; | |
3581 | |
3582 AuxFunctionDefinitionRecordImpl(int offset) { | |
3583 seek(offset); | |
3584 tagIndex = readInt(); | |
3585 totalSize = readInt(); | |
3586 // NOTE zero-basing of this index | |
3587 pointerToLineNumber = readInt() - 1; | |
3588 pointerToNextFunction = readInt(); | |
3589 } | |
3590 | |
3591 public int getTagIndex() { return tagIndex; } | |
3592 public int getTotalSize() { return totalSize; } | |
3593 public int getPointerToLineNumber() { return pointerToLineNumber; } | |
3594 public int getPointerToNextFunction() { return pointerToNextFunction; } | |
3595 public int getType() { return FUNCTION_DEFINITION; } | |
3596 } | |
3597 | |
3598 class AuxBfEfRecordImpl implements AuxBfEfRecord { | |
3599 private short lineNumber; | |
3600 private int pointerToNextFunction; | |
3601 | |
3602 AuxBfEfRecordImpl(int offset) { | |
3603 seek(offset); | |
3604 readInt(); | |
3605 lineNumber = readShort(); | |
3606 readInt(); | |
3607 readShort(); | |
3608 pointerToNextFunction = readInt(); | |
3609 } | |
3610 | |
3611 public short getLineNumber() { return lineNumber; } | |
3612 public int getPointerToNextFunction() { return pointerToNextFunction; } | |
3613 public int getType() { return BF_EF_RECORD; } | |
3614 } | |
3615 | |
3616 class AuxWeakExternalRecordImpl implements AuxWeakExternalRecord { | |
3617 private int tagIndex; | |
3618 private int characteristics; | |
3619 | |
3620 AuxWeakExternalRecordImpl(int offset) { | |
3621 seek(offset); | |
3622 tagIndex = readInt(); | |
3623 characteristics = readInt(); | |
3624 } | |
3625 | |
3626 public int getTagIndex() { return tagIndex; } | |
3627 public int getCharacteristics() { return characteristics; } | |
3628 public int getType() { return WEAK_EXTERNAL; } | |
3629 } | |
3630 | |
3631 class AuxFileRecordImpl implements AuxFileRecord { | |
3632 private String name; | |
3633 | |
3634 AuxFileRecordImpl(int offset) { | |
3635 seek(offset); | |
3636 byte[] tmpName = new byte[18]; | |
3637 int numRead = readBytes(tmpName); | |
3638 if (numRead != 18) { | |
3639 throw new COFFException("Error reading auxiliary file record at offset " + offset); | |
3640 } | |
3641 try { | |
3642 name = new String(tmpName, US_ASCII); | |
3643 } catch (UnsupportedEncodingException e) { | |
3644 throw new COFFException(e); | |
3645 } | |
3646 } | |
3647 | |
3648 public String getName() { return name; } | |
3649 public int getType() { return FILE; } | |
3650 } | |
3651 | |
3652 class AuxSectionDefinitionsRecordImpl implements AuxSectionDefinitionsRecord { | |
3653 private int length; | |
3654 private short numberOfRelocations; | |
3655 private short numberOfLineNumbers; | |
3656 private int checkSum; | |
3657 private short number; | |
3658 private byte selection; | |
3659 | |
3660 AuxSectionDefinitionsRecordImpl(int offset) { | |
3661 seek(offset); | |
3662 length = readInt(); | |
3663 numberOfRelocations = readShort(); | |
3664 numberOfLineNumbers = readShort(); | |
3665 checkSum = readInt(); | |
3666 number = readShort(); | |
3667 selection = readByte(); | |
3668 } | |
3669 | |
3670 public int getLength() { return length; } | |
3671 public short getNumberOfRelocations() { return numberOfRelocations; } | |
3672 public short getNumberOfLineNumbers() { return numberOfLineNumbers; } | |
3673 public int getCheckSum() { return checkSum; } | |
3674 public short getNumber() { return number; } | |
3675 public byte getSelection() { return selection; } | |
3676 public int getType() { return SECTION_DEFINITION; } | |
3677 } | |
3678 | |
3679 class COFFRelocationImpl implements COFFRelocation { | |
3680 private int virtualAddress; | |
3681 private int symbolTableIndex; | |
3682 private short type; | |
3683 | |
3684 COFFRelocationImpl(int offset) { | |
3685 seek(offset); | |
3686 virtualAddress = readInt(); | |
3687 symbolTableIndex = readInt(); | |
3688 type = readShort(); | |
3689 } | |
3690 | |
3691 public int getVirtualAddress() { return virtualAddress; } | |
3692 public int getSymbolTableIndex() { return symbolTableIndex; } | |
3693 public short getType() { return type; } | |
3694 } | |
3695 | |
3696 class COFFLineNumberImpl implements COFFLineNumber { | |
3697 private int type; | |
3698 private short lineNumber; | |
3699 | |
3700 COFFLineNumberImpl(int offset) { | |
3701 seek(offset); | |
3702 type = readInt(); | |
3703 lineNumber = readShort(); | |
3704 } | |
3705 | |
3706 public int getType() { | |
3707 return type; | |
3708 } | |
3709 | |
3710 public short getLineNumber() { | |
3711 return lineNumber; | |
3712 } | |
3713 } | |
3714 | |
3715 class StringTable { | |
3716 class COFFString { | |
3717 String str; | |
3718 int offset; | |
3719 | |
3720 COFFString(String str, int offset) { | |
3721 this.str = str; this.offset = offset; | |
3722 } | |
3723 } | |
3724 | |
3725 COFFString[] strings; | |
3726 | |
3727 StringTable(int offset) { | |
3728 if (offset == 0) { | |
2072
d6cd0d55d0b5
6987812: 2/3 SAJDI: "gHotSpotVMTypes was not initialized properly in the remote process"
dcubed
parents:
1552
diff
changeset
|
3729 // no String Table |
0 | 3730 strings = new COFFString[0]; |
3731 return; | |
3732 } | |
3733 | |
3734 seek(offset); | |
2072
d6cd0d55d0b5
6987812: 2/3 SAJDI: "gHotSpotVMTypes was not initialized properly in the remote process"
dcubed
parents:
1552
diff
changeset
|
3735 int length = readInt(); // length includes itself |
0 | 3736 byte[] data = new byte[length - 4]; |
3737 int numBytesRead = readBytes(data); | |
3738 if (numBytesRead != data.length) { | |
3739 throw new COFFException("Error reading string table (read " + | |
3740 numBytesRead + " bytes, expected to read " + data.length + ")"); | |
3741 } | |
3742 int numStrings = 0; | |
3743 int ptr = 0; | |
3744 for (ptr = 0; ptr < data.length; ptr++) { | |
3745 if (data[ptr] == 0) { | |
3746 numStrings++; | |
3747 } | |
3748 } | |
3749 strings = new COFFString[numStrings]; | |
3750 int lastPtr = 0; | |
3751 ptr = 0; | |
3752 for (int i = 0; i < numStrings; i++) { | |
3753 while (data[ptr] != 0) { | |
3754 ptr++; | |
3755 } | |
3756 try { | |
3757 strings[i] = new COFFString(new String(data, lastPtr, ptr - lastPtr, US_ASCII), | |
3758 offset + ptr + 4); | |
3759 } catch (UnsupportedEncodingException e) { | |
3760 throw new COFFException(e); | |
3761 } | |
3762 ptr++; | |
3763 lastPtr = ptr; | |
3764 } | |
3765 } | |
3766 | |
3767 int getNum() { | |
3768 return strings.length; | |
3769 } | |
3770 | |
3771 String get(int i) { | |
3772 return strings[i].str; | |
3773 } | |
3774 | |
3775 /** This version takes an absolute offset in the file */ | |
3776 String getAtOffset(int offset) { | |
3777 int i = Arrays.binarySearch(strings, new COFFString(null, offset), | |
3778 new Comparator() { | |
3779 public int compare(Object o1, Object o2) { | |
3780 COFFString s1 = (COFFString) o1; | |
3781 COFFString s2 = (COFFString) o2; | |
3782 if (s1.offset == s2.offset) { | |
3783 return 0; | |
3784 } else if (s1.offset < s2.offset) { | |
3785 return -1; | |
3786 } else { | |
3787 return 1; | |
3788 } | |
3789 } | |
3790 }); | |
3791 if (i < 0) { | |
3792 throw new COFFException("No string found at file offset " + offset); | |
3793 } | |
3794 return strings[i].str; | |
3795 } | |
3796 } | |
3797 } | |
3798 | |
3799 void initialize() throws COFFException { | |
3800 // Figure out whether this file is an object file or an image | |
3801 // (either executable or DLL). | |
3802 seek(0x3c); // Error here probably indicates file format error | |
3803 try { | |
3804 int peOffset = readInt(); | |
3805 seek(peOffset); | |
3806 if ((readByte() == (byte) 'P') && | |
3807 (readByte() == (byte) 'E') && | |
3808 (readByte() == (byte) 0) && | |
3809 (readByte() == (byte) 0)) { | |
3810 isImage = true; | |
3811 imageHeaderOffset = getFilePointer(); | |
3812 } | |
3813 } | |
3814 catch (COFFException e) { | |
3815 // Expect failures here if not image file. | |
3816 } | |
3817 } | |
3818 | |
3819 byte readByteAt(long offset) throws COFFException { | |
3820 seek(offset); | |
3821 return readByte(); | |
3822 } | |
3823 | |
3824 byte readByte() throws COFFException { | |
3825 try { | |
3826 return file.readByte(); | |
3827 } catch (IOException e) { | |
3828 throw new COFFException(e.toString() + " at offset 0x" + | |
3829 Long.toHexString(filePos), e); | |
3830 } | |
3831 } | |
3832 | |
3833 int readBytesAt(long offset, byte[] b) throws COFFException { | |
3834 seek(offset); | |
3835 return readBytes(b); | |
3836 } | |
3837 | |
3838 int readBytes(byte[] b) throws COFFException { | |
3839 try { | |
3840 return file.read(b); | |
3841 } catch (IOException e) { | |
3842 throw new COFFException(e.toString() + " at offset 0x" + | |
3843 Long.toHexString(filePos), e); | |
3844 } | |
3845 } | |
3846 | |
3847 /** NOTE: reads little-endian short */ | |
3848 short readShortAt(long offset) throws COFFException { | |
3849 seek(offset); | |
3850 return readShort(); | |
3851 } | |
3852 | |
3853 /** NOTE: reads little-endian short */ | |
3854 short readShort() throws COFFException { | |
3855 try { | |
3856 return byteSwap(file.readShort()); | |
3857 } catch (IOException e) { | |
3858 throw new COFFException(e.toString() + " at offset 0x" + | |
3859 Long.toHexString(filePos), e); | |
3860 } | |
3861 } | |
3862 | |
3863 /** NOTE: reads little-endian int */ | |
3864 int readIntAt(long offset) throws COFFException { | |
3865 seek(offset); | |
3866 return readInt(); | |
3867 } | |
3868 | |
3869 /** NOTE: reads little-endian int */ | |
3870 int readInt() throws COFFException { | |
3871 try { | |
3872 return byteSwap(file.readInt()); | |
3873 } catch (IOException e) { | |
3874 throw new COFFException(e.toString() + " at offset 0x" + | |
3875 Long.toHexString(filePos), e); | |
3876 } | |
3877 } | |
3878 | |
3879 /** NOTE: reads little-endian long */ | |
3880 long readLongAt(long offset) throws COFFException { | |
3881 seek(offset); | |
3882 return readLong(); | |
3883 } | |
3884 | |
3885 /** NOTE: reads little-endian long */ | |
3886 long readLong() throws COFFException { | |
3887 try { | |
3888 return byteSwap(file.readLong()); | |
3889 } catch (IOException e) { | |
3890 throw new COFFException(e.toString() + " at offset 0x" + | |
3891 Long.toHexString(filePos), e); | |
3892 } | |
3893 } | |
3894 | |
3895 /** NOTE: reads little-endian float */ | |
3896 float readFloat() throws COFFException { | |
3897 int i = readInt(); | |
3898 return Float.intBitsToFloat(i); | |
3899 } | |
3900 | |
3901 /** NOTE: reads little-endian double */ | |
3902 double readDouble() throws COFFException { | |
3903 long l = readLong(); | |
3904 return Double.longBitsToDouble(l); | |
3905 } | |
3906 | |
3907 String readCString() throws COFFException { | |
3908 List data = new ArrayList(); | |
3909 byte b = 0; | |
3910 while ((b = readByte()) != 0) { | |
3911 data.add(new Byte(b)); | |
3912 } | |
3913 byte[] bytes = new byte[data.size()]; | |
3914 for (int i = 0; i < data.size(); i++) { | |
3915 bytes[i] = ((Byte) data.get(i)).byteValue(); | |
3916 } | |
3917 try { | |
3918 return new String(bytes, US_ASCII); | |
3919 } catch (UnsupportedEncodingException e) { | |
3920 throw new COFFException(e); | |
3921 } | |
3922 } | |
3923 | |
3924 void seek(long offset) throws COFFException { | |
3925 try { | |
3926 filePos = offset; | |
3927 file.seek(offset); | |
3928 } catch (IOException e) { | |
3929 throw new COFFException(e.toString() + " at offset 0x" + | |
3930 Long.toHexString(offset), e); | |
3931 } | |
3932 } | |
3933 | |
3934 long getFilePointer() throws COFFException { | |
3935 try { | |
3936 return file.getFilePointer(); | |
3937 } catch (IOException e) { | |
3938 throw new COFFException(e); | |
3939 } | |
3940 } | |
3941 | |
3942 short byteSwap(short arg) { | |
3943 return (short) ((arg << 8) | ((arg >>> 8) & 0xFF)); | |
3944 } | |
3945 | |
3946 int byteSwap(int arg) { | |
3947 return (((int) byteSwap((short) arg)) << 16) | (((int) (byteSwap((short) (arg >>> 16)))) & 0xFFFF); | |
3948 } | |
3949 | |
3950 long byteSwap(long arg) { | |
3951 return ((((long) byteSwap((int) arg)) << 32) | (((long) byteSwap((int) (arg >>> 32))) & 0xFFFFFFFF)); | |
3952 } | |
3953 | |
3954 public void close() throws COFFException { | |
3955 try { | |
3956 file.close(); | |
3957 } catch (IOException e) { | |
3958 throw new COFFException(e); | |
3959 } | |
3960 } | |
3961 } | |
3962 } |