Mercurial > hg > truffle
annotate agent/src/share/classes/sun/jvm/hotspot/debugger/win32/coff/COFFFileParser.java @ 2072:d6cd0d55d0b5
6987812: 2/3 SAJDI: "gHotSpotVMTypes was not initialized properly in the remote process"
Summary: Change ExportDirectoryTableImpl to return the 'Export RVA' field without modification. Read 'Base Of Data' field in optional header when PE32 format COFF file is read. Refine search for dbgeng.dll and dbghelp.dll. Other cleanups.
Reviewed-by: swamyv, poonam
author | dcubed |
---|---|
date | Thu, 23 Dec 2010 07:58:35 -0800 |
parents | c18cbe5936b8 |
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 } |