comparison 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
comparison
equal deleted inserted replaced
2071:07c62ff47437 2072:d6cd0d55d0b5
1 /* 1 /*
2 * Copyright (c) 2000, 2004, Oracle and/or its affiliates. All rights reserved. 2 * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 * 4 *
5 * This code is free software; you can redistribute it and/or modify it 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 6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. 7 * published by the Free Software Foundation.
120 private short sizeOfOptionalHeader; 120 private short sizeOfOptionalHeader;
121 private short characteristics; 121 private short characteristics;
122 private MemoizedObject[] sectionHeaders; 122 private MemoizedObject[] sectionHeaders;
123 private MemoizedObject[] symbols; 123 private MemoizedObject[] symbols;
124 124
125 // Init stringTable at decl time since other fields init'ed in the
126 // constructor need the String Table.
125 private MemoizedObject stringTable = new MemoizedObject() { 127 private MemoizedObject stringTable = new MemoizedObject() {
126 public Object computeValue() { 128 public Object computeValue() {
129 // the String Table follows the Symbol Table
127 int ptr = getPointerToSymbolTable(); 130 int ptr = getPointerToSymbolTable();
128 if (ptr == 0) { 131 if (ptr == 0) {
132 // no Symbol Table so no String Table
129 return new StringTable(0); 133 return new StringTable(0);
130 } else { 134 } else {
131 return new StringTable(ptr + SYMBOL_SIZE * getNumberOfSymbols()); 135 return new StringTable(ptr + SYMBOL_SIZE * getNumberOfSymbols());
132 } 136 }
133 } 137 }
138 machine = readShort(); 142 machine = readShort();
139 numberOfSections = readShort(); 143 numberOfSections = readShort();
140 timeDateStamp = readInt(); 144 timeDateStamp = readInt();
141 pointerToSymbolTable = readInt(); 145 pointerToSymbolTable = readInt();
142 numberOfSymbols = readInt(); 146 numberOfSymbols = readInt();
147 // String Table can be accessed at this point because
148 // pointerToSymbolTable and numberOfSymbols fields are set.
143 sizeOfOptionalHeader = readShort(); 149 sizeOfOptionalHeader = readShort();
144 characteristics = readShort(); 150 characteristics = readShort();
145 151
146 // Set up section headers 152 // Set up section headers
147 sectionHeaders = new MemoizedObject[numberOfSections]; 153 sectionHeaders = new MemoizedObject[numberOfSections];
220 private short magic; 226 private short magic;
221 private MemoizedObject standardFields; 227 private MemoizedObject standardFields;
222 private MemoizedObject windowsSpecificFields; 228 private MemoizedObject windowsSpecificFields;
223 private MemoizedObject dataDirectories; 229 private MemoizedObject dataDirectories;
224 230
231 // We use an offset of 2 because OptionalHeaderStandardFieldsImpl doesn't
232 // include the 'magic' field.
225 private static final int STANDARD_FIELDS_OFFSET = 2; 233 private static final int STANDARD_FIELDS_OFFSET = 2;
226 private static final int PE32_WINDOWS_SPECIFIC_FIELDS_OFFSET = 28; 234 private static final int PE32_WINDOWS_SPECIFIC_FIELDS_OFFSET = 28;
227 private static final int PE32_DATA_DIRECTORIES_OFFSET = 96; 235 private static final int PE32_DATA_DIRECTORIES_OFFSET = 96;
228 private static final int PE32_PLUS_WINDOWS_SPECIFIC_FIELDS_OFFSET = 24; 236 private static final int PE32_PLUS_WINDOWS_SPECIFIC_FIELDS_OFFSET = 24;
229 private static final int PE32_PLUS_DATA_DIRECTORIES_OFFSET = 112; 237 private static final int PE32_PLUS_DATA_DIRECTORIES_OFFSET = 112;
286 private int sizeOfCode; 294 private int sizeOfCode;
287 private int sizeOfInitializedData; 295 private int sizeOfInitializedData;
288 private int sizeOfUninitializedData; 296 private int sizeOfUninitializedData;
289 private int addressOfEntryPoint; 297 private int addressOfEntryPoint;
290 private int baseOfCode; 298 private int baseOfCode;
291 private int baseOfData; 299 private int baseOfData; // only set in PE32
292 300
293 OptionalHeaderStandardFieldsImpl(int offset, 301 OptionalHeaderStandardFieldsImpl(int offset,
294 boolean isPE32Plus) { 302 boolean isPE32Plus) {
295 this.isPE32Plus = isPE32Plus; 303 this.isPE32Plus = isPE32Plus;
296 seek(offset); 304 seek(offset);
299 sizeOfCode = readInt(); 307 sizeOfCode = readInt();
300 sizeOfInitializedData = readInt(); 308 sizeOfInitializedData = readInt();
301 sizeOfUninitializedData = readInt(); 309 sizeOfUninitializedData = readInt();
302 addressOfEntryPoint = readInt(); 310 addressOfEntryPoint = readInt();
303 baseOfCode = readInt(); 311 baseOfCode = readInt();
304 if (isPE32Plus) { 312 if (!isPE32Plus) {
313 // only available in PE32
305 baseOfData = readInt(); 314 baseOfData = readInt();
306 } 315 }
307 } 316 }
308 317
309 public byte getMajorLinkerVersion() { return majorLinkerVersion; } 318 public byte getMajorLinkerVersion() { return majorLinkerVersion; }
431 public Object computeValue() { 440 public Object computeValue() {
432 DataDirectory dir = getExportTable(); 441 DataDirectory dir = getExportTable();
433 if (dir.getRVA() == 0 || dir.getSize() == 0) { 442 if (dir.getRVA() == 0 || dir.getSize() == 0) {
434 return null; 443 return null;
435 } 444 }
436 return new ExportDirectoryTableImpl(rvaToFileOffset(dir.getRVA()), dir.getSize()); 445 // ExportDirectoryTableImpl needs both the RVA and the
446 // RVA converted to a file offset.
447 return new
448 ExportDirectoryTableImpl(dir.getRVA(), dir.getSize());
437 } 449 }
438 }; 450 };
439 451
440 debugDirectory = new MemoizedObject() { 452 debugDirectory = new MemoizedObject() {
441 public Object computeValue() { 453 public Object computeValue() {
524 public int getRVA() { return rva; } 536 public int getRVA() { return rva; }
525 public int getSize() { return size; } 537 public int getSize() { return size; }
526 } 538 }
527 539
528 class ExportDirectoryTableImpl implements ExportDirectoryTable { 540 class ExportDirectoryTableImpl implements ExportDirectoryTable {
541 private int exportDataDirRVA;
529 private int offset; 542 private int offset;
530 private int size; 543 private int size;
531 544
532 private int exportFlags; 545 private int exportFlags;
533 private int timeDateStamp; 546 private int timeDateStamp;
546 private MemoizedObject exportNameTable; 559 private MemoizedObject exportNameTable;
547 private MemoizedObject exportNamePointerTable; 560 private MemoizedObject exportNamePointerTable;
548 private MemoizedObject exportOrdinalTable; 561 private MemoizedObject exportOrdinalTable;
549 private MemoizedObject exportAddressTable; 562 private MemoizedObject exportAddressTable;
550 563
551 ExportDirectoryTableImpl(int offset, int size) { 564 ExportDirectoryTableImpl(int exportDataDirRVA, int size) {
552 this.offset = offset; 565 this.exportDataDirRVA = exportDataDirRVA;
566 offset = rvaToFileOffset(exportDataDirRVA);
553 this.size = size; 567 this.size = size;
554 seek(offset); 568 seek(offset);
555 exportFlags = readInt(); 569 exportFlags = readInt();
556 timeDateStamp = readInt(); 570 timeDateStamp = readInt();
557 majorVersion = readShort(); 571 majorVersion = readShort();
593 } 607 }
594 }; 608 };
595 609
596 exportOrdinalTable = new MemoizedObject() { 610 exportOrdinalTable = new MemoizedObject() {
597 public Object computeValue() { 611 public Object computeValue() {
612 // number of ordinals is same as the number of name pointers
598 short[] ordinals = new short[getNumberOfNamePointers()]; 613 short[] ordinals = new short[getNumberOfNamePointers()];
599 seek(rvaToFileOffset(getOrdinalTableRVA())); 614 seek(rvaToFileOffset(getOrdinalTableRVA()));
600 for (int i = 0; i < ordinals.length; i++) { 615 for (int i = 0; i < ordinals.length; i++) {
601 ordinals[i] = readShort(); 616 ordinals[i] = readShort();
602 } 617 }
606 621
607 exportAddressTable = new MemoizedObject() { 622 exportAddressTable = new MemoizedObject() {
608 public Object computeValue() { 623 public Object computeValue() {
609 int[] addresses = new int[getNumberOfAddressTableEntries()]; 624 int[] addresses = new int[getNumberOfAddressTableEntries()];
610 seek(rvaToFileOffset(getExportAddressTableRVA())); 625 seek(rvaToFileOffset(getExportAddressTableRVA()));
611 // Must make two passes to avoid rvaToFileOffset 626 // The Export Address Table values are a union of two
612 // destroying seek() position 627 // possible values:
628 // Export RVA - The address of the exported symbol when
629 // loaded into memory, relative to the image base.
630 // This value doesn't get converted into a file offset.
631 // Forwarder RVA - The pointer to a null-terminated ASCII
632 // string in the export section. This value gets
633 // converted into a file offset because we have to
634 // fetch the string.
613 for (int i = 0; i < addresses.length; i++) { 635 for (int i = 0; i < addresses.length; i++) {
614 addresses[i] = readInt(); 636 addresses[i] = readInt();
615 }
616 for (int i = 0; i < addresses.length; i++) {
617 addresses[i] = rvaToFileOffset(addresses[i]);
618 } 637 }
619 return addresses; 638 return addresses;
620 } 639 }
621 }; 640 };
622 } 641 }
646 return getExportOrdinalTable()[i]; 665 return getExportOrdinalTable()[i];
647 } 666 }
648 667
649 public boolean isExportAddressForwarder(short ordinal) { 668 public boolean isExportAddressForwarder(short ordinal) {
650 int addr = getExportAddress(ordinal); 669 int addr = getExportAddress(ordinal);
651 return ((offset <= addr) && (addr < (offset + size))); 670 return ((exportDataDirRVA <= addr) &&
671 (addr < (exportDataDirRVA + size)));
652 } 672 }
653 673
654 public String getExportAddressForwarder(short ordinal) { 674 public String getExportAddressForwarder(short ordinal) {
655 seek(getExportAddress(ordinal)); 675 seek(rvaToFileOffset(getExportAddress(ordinal)));
656 return readCString(); 676 return readCString();
657 } 677 }
658 678
659 public int getExportAddress(short ordinal) { 679 public int getExportAddress(short ordinal) {
660 680
3369 "at offset " + offset); 3389 "at offset " + offset);
3370 } catch (UnsupportedEncodingException e) { 3390 } catch (UnsupportedEncodingException e) {
3371 throw new COFFException(e); 3391 throw new COFFException(e);
3372 } 3392 }
3373 // Look up in string table 3393 // Look up in string table
3394 // FIXME: this index value is assumed to be in the valid range
3374 name = getStringTable().get(index); 3395 name = getStringTable().get(index);
3375 } else { 3396 } else {
3376 try { 3397 try {
3377 name = new String(tmpName, US_ASCII); 3398 int length = 0;
3399 // find last non-NULL
3400 for (; length < tmpName.length && tmpName[length] != '\0';) {
3401 length++;
3402 }
3403 // don't include NULL chars in returned name String
3404 name = new String(tmpName, 0, length, US_ASCII);
3378 } catch (UnsupportedEncodingException e) { 3405 } catch (UnsupportedEncodingException e) {
3379 throw new COFFException(e); 3406 throw new COFFException(e);
3380 } 3407 }
3381 } 3408 }
3382 virtualSize = readInt(); 3409 virtualSize = readInt();
3485 // FIXME: not sure about byte ordering... 3512 // FIXME: not sure about byte ordering...
3486 int stringOffset = (tmpName[4] << 24 | 3513 int stringOffset = (tmpName[4] << 24 |
3487 tmpName[5] << 16 | 3514 tmpName[5] << 16 |
3488 tmpName[6] << 8 | 3515 tmpName[6] << 8 |
3489 tmpName[7]); 3516 tmpName[7]);
3517 // FIXME: stringOffset is assumed to be in the valid range
3490 name = getStringTable().getAtOffset(stringOffset); 3518 name = getStringTable().getAtOffset(stringOffset);
3491 } 3519 }
3492 3520
3493 value = readInt(); 3521 value = readInt();
3494 sectionNumber = readShort(); 3522 sectionNumber = readShort();
3696 3724
3697 COFFString[] strings; 3725 COFFString[] strings;
3698 3726
3699 StringTable(int offset) { 3727 StringTable(int offset) {
3700 if (offset == 0) { 3728 if (offset == 0) {
3729 // no String Table
3701 strings = new COFFString[0]; 3730 strings = new COFFString[0];
3702 return; 3731 return;
3703 } 3732 }
3704 3733
3705 seek(offset); 3734 seek(offset);
3706 int length = readInt(); 3735 int length = readInt(); // length includes itself
3707 byte[] data = new byte[length - 4]; 3736 byte[] data = new byte[length - 4];
3708 int numBytesRead = readBytes(data); 3737 int numBytesRead = readBytes(data);
3709 if (numBytesRead != data.length) { 3738 if (numBytesRead != data.length) {
3710 throw new COFFException("Error reading string table (read " + 3739 throw new COFFException("Error reading string table (read " +
3711 numBytesRead + " bytes, expected to read " + data.length + ")"); 3740 numBytesRead + " bytes, expected to read " + data.length + ")");