sa-jdi

       }
        else
        {
          try
          {
            int length = 0;
            while ((length < tmpName.length) && (tmpName[length] != 0)) {
              length++;
            }
            name = new String(tmpName, 0, length, "US-ASCII");
          }
          catch (UnsupportedEncodingException e)
          {
            throw new COFFException(e);
          }
        }
        virtualSize = readInt();
        virtualAddress = readInt();
        sizeOfRawData = readInt();
        pointerToRawData = readInt();
        pointerToRelocations = readInt();
        pointerToLineNumbers = readInt();
        numberOfRelocations = readShort();
        numberOfLineNumbers = readShort();
        characteristics = readInt();
        
        relocations = new MemoizedObject[numberOfRelocations];
        for (int i = 0; i < numberOfRelocations; i++)
        {
          final int relocOffset = pointerToRelocations + i * 10;
          relocations[i = new MemoizedObject()
          {
            public Object computeValue()
            {
              return new COFFFileParser.COFFFileImpl.COFFHeaderImpl.COFFRelocationImpl(COFFFileParser.COFFFileImpl.COFFHeaderImpl.this, relocOffset);
            }
          };
        }
        lineNumbers = new MemoizedObject[numberOfLineNumbers];
        for (int i = 0; i < numberOfLineNumbers; i++)
        {
          final int lineNoOffset = pointerToLineNumbers + i * 6;
          lineNumbers[i = new MemoizedObject()
          {
            public Object computeValue()
            {
              return new COFFFileParser.COFFFileImpl.COFFHeaderImpl.COFFLineNumberImpl(COFFFileParser.COFFFileImpl.COFFHeaderImpl.this, lineNoOffset);
            }
          };
        }
      }
      
      public String getName()
      {
        return name;
      }
      
      public int getSize()
      {
        return virtualSize;
      }
      
      public int getVirtualAddress()
      {
        return virtualAddress;
      }
      
      public int getSizeOfRawData()
      {
        return sizeOfRawData;
      }
      
      public int getPointerToRawData()
      {
        return pointerToRawData;
      }
      
      public int getPointerToRelocations()
      {
        return pointerToRelocations;
      }
      
      public int getPointerToLineNumbers()
      {
        return pointerToLineNumbers;
      }
      
      public short getNumberOfRelocations()
      {
        return numberOfRelocations;
      }
      
      public short getNumberOfLineNumbers()
      {
        return numberOfLineNumbers;
      }
      
      public int getSectionFlags()
      {
        return characteristics;
      }
      
      public boolean hasSectionFlag(int flag)
      {
        return (characteristics & flag) != 0;
      }
      
      public COFFRelocation getCOFFRelocation(int index)
      {
        return (COFFRelocation)relocations[index].getValue();
      }
      
      public COFFLineNumber getCOFFLineNumber(int index)
      {
        return (COFFLineNumber)lineNumbers[index];
      }
    }
    
    class COFFSymbolImpl
      implements COFFSymbol, COFFSymbolConstants
    {
      private int offset;
      private String name;
      private int value;
      private short sectionNumber;
      private short type;
      private byte storageClass;
      private byte numberOfAuxSymbols;
      private MemoizedObject auxFunctionDefinitionRecord = new MemoizedObject()
      {
        public Object computeValue()
        {
          return new COFFFileParser.COFFFileImpl.COFFHeaderImpl.AuxFunctionDefinitionRecordImpl(COFFFileParser.COFFFileImpl.COFFHeaderImpl.this, offset + 18);
        }
      };
      private MemoizedObject auxBfEfRecord = new MemoizedObject()
      {
        public Object computeValue()
        {
          return new COFFFileParser.COFFFileImpl.COFFHeaderImpl.AuxBfEfRecordImpl(COFFFileParser.COFFFileImpl.COFFHeaderImpl.this, offset + 18);
        }
      };
      private MemoizedObject auxWeakExternalRecord = new MemoizedObject()
      {
        public Object computeValue()
        {
          return new COFFFileParser.COFFFileImpl.COFFHeaderImpl.AuxWeakExternalRecordImpl(COFFFileParser.COFFFileImpl.COFFHeaderImpl.this, offset + 18);
        }
      };
      private MemoizedObject auxFileRecord = new MemoizedObject()
      {
        public Object computeValue()
        {
          return new COFFFileParser.COFFFileImpl.COFFHeaderImpl.AuxFileRecordImpl(COFFFileParser.COFFFileImpl.COFFHeaderImpl.this, offset + 18);
        }
      };
      private MemoizedObject auxSectionDefinitionsRecord = new MemoizedObject()
      {
        public Object computeValue()
        {
          return new COFFFileParser.COFFFileImpl.COFFHeaderImpl.AuxSectionDefinitionsRecordImpl(COFFFileParser.COFFFileImpl.COFFHeaderImpl.this, offset + 18);
        }
      };
      
      public COFFSymbolImpl(int offset)
        throws COFFException
      {
        this.offset = offset;
        seek(offset);
        
        byte[] tmpName = new byte[8];
        int numRead = readBytes(tmpName);
        if (numRead != 8) {
          throw new COFFException("Error reading name of symbol at offset " + offset);
        }
        if ((tmpName[0] == 0) && (tmpName[1] == 0) && (tmpName[2] == 0) && (tmpName[3] == 0))
        {
          int stringOffset = tmpName[4] << 24 | tmpName[5] << 16 | tmpName[6] << 8 | tmpName[7];
          
          name = getStringTable().getAtOffset(stringOffset);
        }
        value = readInt();
        sectionNumber = readShort();
        type = readShort();
        storageClass = readByte();
        numberOfAuxSymbols = readByte();
      }
      
      public int getOffset()
      {
        return offset;
      }
      
      public String getName()
      {
        return name;
      }
      
      public int getValue()
      {
        return value;
      }
      
      public short getSectionNumber()
      {
        return sectionNumber;
      }
      
      public short getType()
      {
        return type;
      }
      
      public byte getStorageClass()
      {
        return storageClass;
      }
      
      public byte getNumberOfAuxSymbols()
      {
        return numberOfAuxSymbols;
      }
      
      public boolean isFunctionDefinition()
      {
        return (getStorageClass() == 2) && (getType() >>> 8 == 2) && (getSectionNumber() > 0);
      }
      
      public AuxFunctionDefinitionRecord getAuxFunctionDefinitionRecord()
      {
        return (AuxFunctionDefinitionRecord)auxFunctionDefinitionRecord.getValue();
      }
      
      public boolean isBfOrEfSymbol()
      {
        return ((getName().equals(".bf")) || (getName().equals(".ef"))) && (getStorageClass() == 101);
      }
      
      public AuxBfEfRecord getAuxBfEfRecord()
      {
        return (AuxBfEfRecord)auxBfEfRecord.getValue();
      }
      
      public boolean isWeakExternal()
      {
        return (getStorageClass() == 2) && (getSectionNumber() == 0) && (getValue() == 0);
      }
      
      public AuxWeakExternalRecord getAuxWeakExternalRecord()
      {
        return (AuxWeakExternalRecord)auxWeakExternalRecord.getValue();
      }
      
      public boolean isFile()
      {
        return (getName().equals(".file")) && (getStorageClass() == 103);
      }
      
      public AuxFileRecord getAuxFileRecord()
      {
        return (AuxFileRecord)auxFileRecord.getValue();
      }
      
      public boolean isSectionDefinition()
      {
        return (getName().charAt(0) == '.') && (getStorageClass() == 3);
      }
      
      public AuxSectionDefinitionsRecord getAuxSectionDefinitionsRecord()
      {
        return (AuxSectionDefinitionsRecord)auxSectionDefinitionsRecord.getValue();
      }
    }
    
    class AuxFunctionDefinitionRecordImpl
      implements AuxFunctionDefinitionRecord
    {
      private int tagIndex;
      private int totalSize;
      private int pointerToLineNumber;
      private int pointerToNextFunction;
      
      AuxFunctionDefinitionRecordImpl(int offset)
      {
        seek(offset);
        tagIndex = readInt();
        totalSize = readInt();
        
        pointerToLineNumber = (readInt() - 1);
        pointerToNextFunction = readInt();
      }
      
      public int getTagIndex()
      {
        return tagIndex;
      }
      
      public int getTotalSize()
      {
        return totalSize;
      }
      
      public int getPointerToLineNumber()
      {
        return pointerToLineNumber;
      }
      
      public int getPointerToNextFunction()
      {
        return pointerToNextFunction;
      }
      
      public int getType()
      {
        return 0;
      }
    }
    
    class AuxBfEfRecordImpl
      implements AuxBfEfRecord
    {
      private short lineNumber;
      private int pointerToNextFunction;
      
      AuxBfEfRecordImpl(int offset)
      {
        seek(offset);
        readInt();
        lineNumber = readShort();
        readInt();
        readShort();
        pointerToNextFunction = readInt();
      }
      
      public short getLineNumber()
      {
        return lineNumber;
      }
      
      public int getPointerToNextFunction()
      {
        return pointerToNextFunction;
      }
      
      public int getType()
      {
        return 1;
      }
    }
    
    class AuxWeakExternalRecordImpl
      implements AuxWeakExternalRecord
    {
      private int tagIndex;
      private int characteristics;
      
      AuxWeakExternalRecordImpl(int offset)
      {
        seek(offset);
        tagIndex = readInt();
        characteristics = readInt();
      }
      
      public int getTagIndex()
      {
        return tagIndex;
      }
      
      public int getCharacteristics()
      {
        return characteristics;
      }
      
      public int getType()
      {
        return 2;
      }
    }
    
    class AuxFileRecordImpl
      implements AuxFileRecord
    {
      private String name;
      
      AuxFileRecordImpl(int offset)
      {
        seek(offset);
        byte[] tmpName = new byte[18];
        int numRead = readBytes(tmpName);
        if (numRead != 18) {
          throw new COFFException("Error reading auxiliary file record at offset " + offset);
        }
        try
        {
          name = new String(tmpName, "US-ASCII");
        }
        catch (UnsupportedEncodingException e)
        {
          throw new COFFException(e);
        }
      }
      
      public String getName()
      {
        return name;
      }
      
      public int getType()
      {
        return 3;
      }
    }
    
    class AuxSectionDefinitionsRecordImpl
      implements AuxSectionDefinitionsRecord
    {
      private int length;
      private short numberOfRelocations;
      private short numberOfLineNumbers;
      private int checkSum;
      private short number;
      private byte selection;
      
      AuxSectionDefinitionsRecordImpl(int offset)
      {
        seek(offset);
        length = readInt();
        numberOfRelocations = readShort();
        numberOfLineNumbers = readShort();
        checkSum = readInt();
        number = readShort();
        selection = readByte();
      }
      
      public int getLength()
      {
        return length;
      }
      
      public short getNumberOfRelocations()
      {
        return numberOfRelocations;
      }
      
      public short getNumberOfLineNumbers()
      {
        return numberOfLineNumbers;
      }
      
      public int getCheckSum()
      {
        return checkSum;
      }
      
      public short getNumber()
      {
        return number;
      }
      
      public byte getSelection()
      {
        return selection;
      }
      
      public int getType()
      {
        return 4;
      }
    }
    
    class COFFRelocationImpl
      implements COFFRelocation
    {
      private int virtualAddress;
      private int symbolTableIndex;
      private short type;
      
      COFFRelocationImpl(int offset)
      {
        seek(offset);
        virtualAddress = readInt();
        symbolTableIndex = readInt();
        type = readShort();
      }
      
      public int getVirtualAddress()
      {
        return virtualAddress;
      }
      
      public int getSymbolTableIndex()
      {
        return symbolTableIndex;
      }
      
      public short getType()
      {
        return type;
      }
    }
    
    class COFFLineNumberImpl
      implements COFFLineNumber
    {
      private int type;
      private short lineNumber;
      
      COFFLineNumberImpl(int offset)
      {
        seek(offset);
        type = readInt();
        lineNumber = readShort();
      }
      
      public int getType()
      {
        return type;
      }
      
      public short getLineNumber()
      {
        return lineNumber;
      }
    }
    
    class StringTable
    {
      COFFString[] strings;
      
      class COFFString
      {
        String str;
        int offset;
        
        COFFString(String str, int offset)
        {
          this.str = str;this.offset = offset;
        }
      }
      
      StringTable(int offset)
      {
        if (offset == 0)
        {
          strings = new COFFString[0];
          return;
        }
        seek(offset);
        int length = readInt();
        byte[] data = new byte[length - 4];
        int numBytesRead = readBytes(data);
        if (numBytesRead != data.length) {
          throw new COFFException("Error reading string table (read " + numBytesRead + " bytes, expected to read " + data.length + ")");
        }
        int numStrings = 0;
        int ptr = 0;
        for (ptr = 0; ptr < data.length; ptr++) {
          if (data[ptr] == 0) {
            numStrings++;
          }
        }
        strings = new COFFString[numStrings];
        int lastPtr = 0;
        ptr = 0;
        for (int i = 0; i < numStrings; i++)
        {
          while (data[ptr] != 0) {
            ptr++;
          }
          try
          {
            strings[i] = new COFFString(new String(data, lastPtr, ptr - lastPtr, "US-ASCII"), offset + ptr + 4);
          }
          catch (UnsupportedEncodingException e)
          {
            throw new COFFException(e);
          }
          ptr++;
          lastPtr = ptr;
        }
      }
      
      int getNum()
      {
        return strings.length;
      }
      
      String get(int i)
      {
        return strings[i].str;
      }
      
      String getAtOffset(int offset)
      {
        int i = Arrays.binarySearch(strings, new COFFString(null, offset), new Comparator()
        {
          public int compare(Object o1, Object o2)
          {
            COFFFileParser.COFFFileImpl.COFFHeaderImpl.StringTable.COFFString s1 = (COFFFileParser.COFFFileImpl.COFFHeaderImpl.StringTable.COFFString)o1;
            COFFFileParser.COFFFileImpl.COFFHeaderImpl.StringTable.COFFString s2 = (COFFFileParser.COFFFileImpl.COFFHeaderImpl.StringTable.COFFString)o2;
            if (offset == offset) {
              return 0;
            }
            if (offset < offset) {
              return -1;
            }
            return 1;
          }
        });
        if (i < 0) {
          throw new COFFException("No string found at file offset " + offset);
        }
        return strings[i].str;
      }
    }
  }
  
  void initialize()
    throws COFFException
  {
    seek(60L);
    try
    {
      int peOffset = readInt();
      seek(peOffset);
      if ((readByte() == 80) && (readByte() == 69) && (readByte() == 0) && (readByte() == 0))
      {
        isImage = true;
        imageHeaderOffset = getFilePointer();
      }
    }
    catch (COFFException e) {}
  }
  
  byte readByteAt(long offset)
    throws COFFException
  {
    seek(offset);
    return readByte();
  }
  
  byte readByte()
    throws COFFException
  {
    try
    {
      return file.readByte();
    }
    catch (IOException e)
    {
      throw new COFFException(e.toString() + " at offset 0x" + Long.toHexString(filePos), e);
    }
  }
  
  int readBytesAt(long offset, byte[] b)
    throws COFFException
  {
    seek(offset);
    return readBytes(b);
  }
  
  int readBytes(byte[] b)
    throws COFFException
  {
    try
    {
      return file.read(b);
    }
    catch (IOException e)
    {
      throw new COFFException(e.toString() + " at offset 0x" + Long.toHexString(filePos), e);
    }
  }
  
  short readShortAt(long offset)
    throws COFFException
  {
    seek(offset);
    return readShort();
  }
  
  short readShort()
    throws COFFException
  {
    try
    {
      return byteSwap(file.readShort());
    }
    catch (IOException e)
    {
      throw new COFFException(e.toString() + " at offset 0x" + Long.toHexString(filePos), e);
    }
  }
  
  int readIntAt(long offset)
    throws COFFException
  {
    seek(offset);
    return readInt();
  }
  
  int readInt()
    throws COFFException
  {
    try
    {
      return byteSwap(file.readInt());
    }
    catch (IOException e)
    {
      throw new COFFException(e.toString() + " at offset 0x" + Long.toHexString(filePos), e);
    }
  }
  
  long readLongAt(long offset)
    throws COFFException
  {
    seek(offset);
    return readLong();
  }
  
  long readLong()
    throws COFFException
  {
    try
    {
      return byteSwap(file.readLong());
    }
    catch (IOException e)
    {
      throw new COFFException(e.toString() + " at offset 0x" + Long.toHexString(filePos), e);
    }
  }
  
  float readFloat()
    throws COFFException
  {
    int i = readInt();
    return Float.intBitsToFloat(i);
  }
  
  double readDouble()
    throws COFFException
  {
    long l = readLong();
    return Double.longBitsToDouble(l);
  }
  
  String readCString()
    throws COFFException
  {
    List data = new ArrayList();
    byte b = 0;
    while ((b = readByte()) != 0) {
      data.add(new Byte(b));
    }
    byte[] bytes = new byte[data.size()];
    for (int i = 0; i < data.size(); i++) {
      bytes[i] = ((Byte)data.get(i)).byteValue();
    }
    try
    {
      return new String(bytes, "US-ASCII");
    }
    catch (UnsupportedEncodingException e)
    {
      throw new COFFException(e);
    }
  }
  
  void seek(long offset)
    throws COFFException
  {
    try
    {
      filePos = offset;
      file.seek(offset);
    }
    catch (IOException e)
    {
      throw new COFFException(e.toString() + " at offset 0x" + Long.toHexString(offset), e);
    }
  }
  
  long getFilePointer()
    throws COFFException
  {
    try
    {
      return file.getFilePointer();
    }
    catch (IOException e)
    {
      throw new COFFException(e);
    }
  }
  
  short byteSwap(short arg)
  {
    return (short)(arg << 8 | arg >>> 8 & 0xFF);
  }
  
  int byteSwap(int arg)
  {
    return byteSwap((short)arg) << 16 | byteSwap((short)(arg >>> 16)) & 0xFFFF;
  }
  
  long byteSwap(long arg)
  {
    return byteSwap((int)arg) << 32 | byteSwap((int)(arg >>> 32)) & 0xFFFFFFFFFFFFFFFF;
  }
  
  public void close()
    throws COFFException
  {
    try
    {
      file.close();
    }
    catch (IOException e)
    {
      throw new COFFException(e);
    }
  }
}

/* Location:
 * Qualified Name:     sun.jvm.hotspot.debugger.win32.coff.COFFFileParser.COFFFileImpl
 * Java Class Version: 1.4 (48.0)
 * JD-Core Version:    0.7.1
 */
package sun.jvm.hotspot.debugger.win32.coff;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannel.MapMode;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.NoSuchElementException;
import sun.jvm.hotspot.debugger.DataSource;
import sun.jvm.hotspot.debugger.MappedByteBufferDataSource;
import sun.jvm.hotspot.utilities.Assert;
import sun.jvm.hotspot.utilities.memo.MemoizedObject;

public class COFFFileParser
{
  private static COFFFileParser soleInstance;
  private static final int COFF_HEADER_SIZE = 20;
  private static final int SECTION_HEADER_SIZE = 40;
  private static final int SYMBOL_SIZE = 18;
  private static final int RELOCATION_SIZE = 10;
  private static final int LINE_NUMBER_SIZE = 6;
  private static final String US_ASCII = "US-ASCII";
  
  public static COFFFileParser getParser()
  {
    if (soleInstance == null) {
      soleInstance = new COFFFileParser();
    }
    return soleInstance;
  }
  
  public COFFFile parse(String filename)
    throws COFFException
  {
    try
    {
      File file = new File(filename);
      FileInputStream stream = new FileInputStream(file);
      MappedByteBuffer buf = stream.getChannel().map(FileChannel.MapMode.READ_ONLY, 0L, file.length());
      
      return parse(new MappedByteBufferDataSource(buf));
    }
    catch (FileNotFoundException e)
    {
      throw new COFFException(e);
    }
    catch (IOException e)
    {
      throw new COFFException(e);
    }
  }
  
  public COFFFile parse(DataSource source)
    throws COFFException
  {
    return new COFFFileImpl(source);
  }
  
  class COFFFileImpl
    implements COFFFile
  {
    private DataSource file;
    private long filePos;
    private boolean isImage;
    private long imageHeaderOffset;
    private MemoizedObject header = new MemoizedObject()
    {
      public Object computeValue()
      {
        return new COFFFileParser.COFFFileImpl.COFFHeaderImpl(COFFFileParser.COFFFileImpl.this);
      }
    };
    
    COFFFileImpl(DataSource file)
      throws COFFException
    {
      this.file = file;
      initialize();
    }
    
    public boolean isImage()
    {
      return isImage;
    }
    
    public COFFHeader getHeader()
    {
      return (COFFHeaderImpl)header.getValue();
    }
    
    class COFFHeaderImpl
      implements COFFHeader
    {
      private short machine;
      private short numberOfSections;
      private int timeDateStamp;
      private int pointerToSymbolTable;
      private int numberOfSymbols;
      private short sizeOfOptionalHeader;
      private short characteristics;
      private MemoizedObject[] sectionHeaders;
      private MemoizedObject[] symbols;
      private MemoizedObject stringTable = new MemoizedObject()
      {
        public Object computeValue()
        {
          int ptr = getPointerToSymbolTable();
          if (ptr == 0) {
            return new COFFFileParser.COFFFileImpl.COFFHeaderImpl.StringTable(COFFFileParser.COFFFileImpl.COFFHeaderImpl.this, 0);
          }
          return new COFFFileParser.COFFFileImpl.COFFHeaderImpl.StringTable(COFFFileParser.COFFFileImpl.COFFHeaderImpl.this, ptr + 18 * getNumberOfSymbols());
        }
      };
      
      COFFHeaderImpl()
      {
        seek(imageHeaderOffset);
        machine = readShort();
        numberOfSections = readShort();
        timeDateStamp = readInt();
        pointerToSymbolTable = readInt();
        numberOfSymbols = readInt();
        
        sizeOfOptionalHeader = readShort();
        characteristics = readShort();
        
        sectionHeaders = new MemoizedObject[numberOfSections];
        for (int i = 0; i < numberOfSections; i++)
        {
          final int secHdrOffset = (int)(imageHeaderOffset + 20L + sizeOfOptionalHeader + i * 40);
          
          sectionHeaders[i = new MemoizedObject()
          {
            public Object computeValue()
            {
              return new COFFFileParser.COFFFileImpl.COFFHeaderImpl.SectionHeaderImpl(COFFFileParser.COFFFileImpl.COFFHeaderImpl.this, secHdrOffset);
            }
          };
        }
        symbols = new MemoizedObject[numberOfSymbols];
        for (int i = 0; i < numberOfSymbols; i++)
        {
          final int symbolOffset = pointerToSymbolTable + i * 18;
          symbols[i = new MemoizedObject()
          {
            public Object computeValue()
            {
              return new COFFFileParser.COFFFileImpl.COFFHeaderImpl.COFFSymbolImpl(COFFFileParser.COFFFileImpl.COFFHeaderImpl.this, symbolOffset);
            }
          };
        }
      }
      
      public short getMachineType()
      {
        return machine;
      }
      
      public short getNumberOfSections()
      {
        return numberOfSections;
      }
      
      public int getTimeDateStamp()
      {
        return timeDateStamp;
      }
      
      public int getPointerToSymbolTable()
      {
        return pointerToSymbolTable;
      }
      
      public int getNumberOfSymbols()
      {
        return numberOfSymbols;
      }
      
      public short getSizeOfOptionalHeader()
      {
        return sizeOfOptionalHeader;
      }
      
      public OptionalHeader getOptionalHeader()
        throws COFFException
      {
        if (getSizeOfOptionalHeader() == 0) {
          return null;
        }
        return new OptionalHeaderImpl((int)(imageHeaderOffset + 20L));
      }
      
      public short getCharacteristics()
      {
        return characteristics;
      }
      
      public boolean hasCharacteristic(short characteristic)
      {
        return (characteristics & characteristic) != 0;
      }
      
      public SectionHeader getSectionHeader(int index)
      {
        return (SectionHeader)sectionHeaders[(index - 1)].getValue();
      }
      
      public COFFSymbol getCOFFSymbol(int index)
      {
        return (COFFSymbol)symbols[index].getValue();
      }
      
      public int getNumberOfStrings()
      {
        return getStringTable().getNum();
      }
      
      public String getString(int i)
      {
        return getStringTable().get(i);
      }
      
      StringTable getStringTable()
      {
        return (StringTable)stringTable.getValue();
      }
      
      int rvaToFileOffset(int rva)
      {
        if (rva == 0) {
          return 0;
        }
        for (int i = 1; i <= getNumberOfSections(); i++)
        {
          SectionHeader sec = getSectionHeader(i);
          int va = sec.getVirtualAddress();
          int sz = sec.getSize();
          if ((va <= rva) && (rva < va + sz)) {
            return sec.getPointerToRawData() + (rva - va);
          }
        }
        throw new COFFException("Unable to find RVA 0x" + Integer.toHexString(rva) + " in any section");
      }
      
      class OptionalHeaderImpl
        implements OptionalHeader
      {
        private short magic;
        private MemoizedObject standardFields;
        private MemoizedObject windowsSpecificFields;
        private MemoizedObject dataDirectories;
        private static final int STANDARD_FIELDS_OFFSET = 2;
        private static final int PE32_WINDOWS_SPECIFIC_FIELDS_OFFSET = 28;
        private static final int PE32_DATA_DIRECTORIES_OFFSET = 96;
        private static final int PE32_PLUS_WINDOWS_SPECIFIC_FIELDS_OFFSET = 24;
        private static final int PE32_PLUS_DATA_DIRECTORIES_OFFSET = 112;
        
        OptionalHeaderImpl(int offset)
        {
          seek(offset);
          magic = readShort();
          
          final boolean isPE32Plus = magic == 523;
          final int standardFieldsOffset = offset + 2;
          final int windowsSpecificFieldsOffset = offset + (isPE32Plus ? 24 : 28);
          
          final int dataDirectoriesOffset = offset + (isPE32Plus ? 112 : 96);
          
          standardFields = new MemoizedObject()
          {
            public Object computeValue()
            {
              return new COFFFileParser.COFFFileImpl.COFFHeaderImpl.OptionalHeaderStandardFieldsImpl(COFFFileParser.COFFFileImpl.COFFHeaderImpl.this, standardFieldsOffset, isPE32Plus);
            }
          };
          windowsSpecificFields = new MemoizedObject()
          {
            public Object computeValue()
            {
              return new COFFFileParser.COFFFileImpl.COFFHeaderImpl.OptionalHeaderWindowsSpecificFieldsImpl(COFFFileParser.COFFFileImpl.COFFHeaderImpl.this, windowsSpecificFieldsOffset, isPE32Plus);
            }
          };
          dataDirectories = new MemoizedObject()
          {
            public Object computeValue()
            {
              return new COFFFileParser.COFFFileImpl.COFFHeaderImpl.OptionalHeaderDataDirectoriesImpl(COFFFileParser.COFFFileImpl.COFFHeaderImpl.this, dataDirectoriesOffset, getWindowsSpecificFields().getNumberOfRvaAndSizes());
            }
          };
        }
        
        public short getMagicNumber()
        {
          return magic;
        }
        
        public OptionalHeaderStandardFields getStandardFields()
        {
          return (OptionalHeaderStandardFields)standardFields.getValue();
        }
        
        public OptionalHeaderWindowsSpecificFields getWindowsSpecificFields()
        {
          return (OptionalHeaderWindowsSpecificFields)windowsSpecificFields.getValue();
        }
        
        public OptionalHeaderDataDirectories getDataDirectories()
        {
          return (OptionalHeaderDataDirectories)dataDirectories.getValue();
        }
      }
      
      class OptionalHeaderStandardFieldsImpl
        implements OptionalHeaderStandardFields
      {
        private boolean isPE32Plus;
        private byte majorLinkerVersion;
        private byte minorLinkerVersion;
        private int sizeOfCode;
        private int sizeOfInitializedData;
        private int sizeOfUninitializedData;
        private int addressOfEntryPoint;
        private int baseOfCode;
        private int baseOfData;
        
        OptionalHeaderStandardFieldsImpl(int offset, boolean isPE32Plus)
        {
          this.isPE32Plus = isPE32Plus;
          seek(offset);
          majorLinkerVersion = readByte();
          minorLinkerVersion = readByte();
          sizeOfCode = readInt();
          sizeOfInitializedData = readInt();
          sizeOfUninitializedData = readInt();
          addressOfEntryPoint = readInt();
          baseOfCode = readInt();
          if (!isPE32Plus) {
            baseOfData = readInt();
          }
        }
        
        public byte getMajorLinkerVersion()
        {
          return majorLinkerVersion;
        }
        
        public byte getMinorLinkerVersion()
        {
          return minorLinkerVersion;
        }
        
        public int getSizeOfCode()
        {
          return sizeOfCode;
        }
        
        public int getSizeOfInitializedData()
        {
          return sizeOfInitializedData;
        }
        
        public int getSizeOfUninitializedData()
        {
          return sizeOfUninitializedData;
        }
        
        public int getAddressOfEntryPoint()
        {
          return addressOfEntryPoint;
        }
        
        public int getBaseOfCode()
        {
          return baseOfCode;
        }
        
        public int getBaseOfData()
          throws COFFException
        {
          if (isPE32Plus) {
            throw new COFFException("Not present in PE32+ files");
          }
          return baseOfData;
        }
      }
      
      class OptionalHeaderWindowsSpecificFieldsImpl
        implements OptionalHeaderWindowsSpecificFields
      {
        private long imageBase;
        private int sectionAlignment;
        private int fileAlignment;
        private short majorOperatingSystemVersion;
        private short minorOperatingSystemVersion;
        private short majorImageVersion;
        private short minorImageVersion;
        private short majorSubsystemVersion;
        private short minorSubsystemVersion;
        private int sizeOfImage;
        private int sizeOfHeaders;
        private int checkSum;
        private short subsystem;
        private short dllCharacteristics;
        private long sizeOfStackReserve;
        private long sizeOfStackCommit;
        private long sizeOfHeapReserve;
        private long sizeOfHeapCommit;
        private int loaderFlags;
        private int numberOfRvaAndSizes;
        
        OptionalHeaderWindowsSpecificFieldsImpl(int offset, boolean isPE32Plus)
        {
          seek(offset);
          if (!isPE32Plus) {
            imageBase = maskInt(readInt());
          } else {
            imageBase = readLong();
          }
          sectionAlignment = readInt();
          fileAlignment = readInt();
          majorOperatingSystemVersion = readShort();
          minorOperatingSystemVersion = readShort();
          majorImageVersion = readShort();
          minorImageVersion = readShort();
          majorSubsystemVersion = readShort();
          minorSubsystemVersion = readShort();
          readInt();
          sizeOfImage = readInt();
          sizeOfHeaders = readInt();
          checkSum = readInt();
          subsystem = readShort();
          dllCharacteristics = readShort();
          if (!isPE32Plus)
          {
            sizeOfStackReserve = maskInt(readInt());
            sizeOfStackCommit = maskInt(readInt());
            sizeOfHeapReserve = maskInt(readInt());
            sizeOfHeapCommit = maskInt(readInt());
          }
          else
          {
            sizeOfStackReserve = readLong();
            sizeOfStackCommit = readLong();
            sizeOfHeapReserve = readLong();
            sizeOfHeapCommit = readLong();
          }
          loaderFlags = readInt();
          numberOfRvaAndSizes = readInt();
        }
        
        public long getImageBase()
        {
          return imageBase;
        }
        
        public int getSectionAlignment()
        {
          return sectionAlignment;
        }
        
        public int getFileAlignment()
        {
          return fileAlignment;
        }
        
        public short getMajorOperatingSystemVersion()
        {
          return majorOperatingSystemVersion;
        }
        
        public short getMinorOperatingSystemVersion()
        {
          return minorOperatingSystemVersion;
        }
        
        public short getMajorImageVersion()
        {
          return majorImageVersion;
        }
        
        public short getMinorImageVersion()
        {
          return minorImageVersion;
        }
        
        public short getMajorSubsystemVersion()
        {
          return majorSubsystemVersion;
        }
        
        public short getMinorSubsystemVersion()
        {
          return minorSubsystemVersion;
        }
        
        public int getSizeOfImage()
        {
          return sizeOfImage;
        }
        
        public int getSizeOfHeaders()
        {
          return sizeOfHeaders;
        }
        
        public int getCheckSum()
        {
          return checkSum;
        }
        
        public short getSubsystem()
        {
          return subsystem;
        }
        
        public short getDLLCharacteristics()
        {
          return dllCharacteristics;
        }
        
        public long getSizeOfStackReserve()
        {
          return sizeOfStackReserve;
        }
        
        public long getSizeOfStackCommit()
        {
          return sizeOfStackCommit;
        }
        
        public long getSizeOfHeapReserve()
        {
          return sizeOfHeapReserve;
        }
        
        public long getSizeOfHeapCommit()
        {
          return sizeOfHeapCommit;
        }
        
        public int getLoaderFlags()
        {
          return loaderFlags;
        }
        
        public int getNumberOfRvaAndSizes()
        {
          return numberOfRvaAndSizes;
        }
        
        private long maskInt(long arg)
        {
          return arg & 0xFFFFFFFF;
        }
      }
      
      class OptionalHeaderDataDirectoriesImpl
        implements OptionalHeaderDataDirectories
      {
        private int numberOfRvaAndSizes;
        private MemoizedObject[] dataDirectories;
        private MemoizedObject exportDirectoryTable;
        private MemoizedObject debugDirectory;
        private static final int DATA_DIRECTORY_SIZE = 8;
        
        OptionalHeaderDataDirectoriesImpl(int offset, int numberOfRvaAndSizes)
        {
          this.numberOfRvaAndSizes = numberOfRvaAndSizes;
          dataDirectories = new MemoizedObject[numberOfRvaAndSizes];
          for (int i = 0; i < numberOfRvaAndSizes; i++)
          {
            final int dirOffset = offset + i * 8;
            dataDirectories[i = new MemoizedObject()
            {
              public Object computeValue()
              {
                return new COFFFileParser.COFFFileImpl.COFFHeaderImpl.DataDirectoryImpl(COFFFileParser.COFFFileImpl.COFFHeaderImpl.this, dirOffset);
              }
            };
          }
          exportDirectoryTable = new MemoizedObject()
          {
            public Object computeValue()
            {
              DataDirectory dir = getExportTable();
              if ((dir.getRVA() == 0) || (dir.getSize() == 0)) {
                return null;
              }
              return new COFFFileParser.COFFFileImpl.COFFHeaderImpl.ExportDirectoryTableImpl(COFFFileParser.COFFFileImpl.COFFHeaderImpl.this, dir.getRVA(), dir.getSize());
            }
          };
          debugDirectory = new MemoizedObject()
          {
            public Object computeValue()
            {
              DataDirectory dir = getDebug();
              if ((dir.getRVA() == 0) || (dir.getSize() == 0)) {
                return null;
              }
              return new COFFFileParser.COFFFileImpl.COFFHeaderImpl.DebugDirectoryImpl(COFFFileParser.COFFFileImpl.COFFHeaderImpl.this, rvaToFileOffset(dir.getRVA()), dir.getSize());
            }
          };
        }
        
        public DataDirectory getExportTable()
          throws COFFException
        {
          return (DataDirectory)dataDirectories[checkIndex(0)].getValue();
        }
        
        public DataDirectory getImportTable()
          throws COFFException
        {
          return (DataDirectory)dataDirectories[checkIndex(1)].getValue();
        }
        
        public DataDirectory getResourceTable()
          throws COFFException
        {
          return (DataDirectory)dataDirectories[checkIndex(2)].getValue();
        }
        
        public DataDirectory getExceptionTable()
          throws COFFException
        {
          return (DataDirectory)dataDirectories[checkIndex(3)].getValue();
        }
        
        public DataDirectory getCertificateTable()
          throws COFFException
        {
          return (DataDirectory)dataDirectories[checkIndex(4)].getValue();
        }
        
        public DataDirectory getBaseRelocationTable()
          throws COFFException
        {
          return (DataDirectory)dataDirectories[checkIndex(5)].getValue();
        }
        
        public DataDirectory getDebug()
          throws COFFException
        {
          return (DataDirectory)dataDirectories[checkIndex(6)].getValue();
        }
        
        public DataDirectory getArchitecture()
          throws COFFException
        {
          return (DataDirectory)dataDirectories[checkIndex(7)].getValue();
        }
        
        public DataDirectory getGlobalPtr()
          throws COFFException
        {
          return (DataDirectory)dataDirectories[checkIndex(8)].getValue();
        }
        
        public DataDirectory getTLSTable()
          throws COFFException
        {
          return (DataDirectory)dataDirectories[checkIndex(9)].getValue();
        }
        
        public DataDirectory getLoadConfigTable()
          throws COFFException
        {
          return (DataDirectory)dataDirectories[checkIndex(10)].getValue();
        }
        
        public DataDirectory getBoundImportTable()
          throws COFFException
        {
          return (DataDirectory)dataDirectories[checkIndex(11)].getValue();
        }
        
        public DataDirectory getImportAddressTable()
          throws COFFException
        {
          return (DataDirectory)dataDirectories[checkIndex(12)].getValue();
        }
        
        public DataDirectory getDelayImportDescriptor()
          throws COFFException
        {
          return (
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114

Further reading...

For more information on Java 1.5 Tiger, you may find Java 1.5 Tiger, A developer's Notebook by D. Flanagan and B. McLaughlin from O'Reilly of interest.

New!JAR listings


Copyright 2006-2019. Infinite Loop Ltd