sa-jdi

s, typeStringOffset + 2, len);
          }
          
          public short getBClassAttribute()
          {
            typeSeek(2);
            return readShort();
          }
          
          public int getBClassType()
          {
            typeSeek(4);
            return readInt();
          }
          
          public int getBClassOffset()
            throws DebugVC50WrongNumericTypeException
          {
            return readIntNumericLeafAt(8);
          }
          
          public short getVBClassAttribute()
          {
            typeSeek(2);
            return readShort();
          }
          
          public int getVBClassBaseClassType()
          {
            typeSeek(4);
            return readInt();
          }
          
          public int getVBClassVirtualBaseClassType()
          {
            typeSeek(8);
            return readInt();
          }
          
          public int getVBClassVBPOff()
            throws DebugVC50WrongNumericTypeException
          {
            return readIntNumericLeafAt(12);
          }
          
          public int getVBClassVBOff()
            throws DebugVC50WrongNumericTypeException
          {
            return readIntNumericLeafAt(12 + numericLeafLengthAt(12));
          }
          
          public short getIVBClassAttribute()
          {
            typeSeek(2);
            return readShort();
          }
          
          public int getIVBClassBType()
          {
            typeSeek(4);
            return readInt();
          }
          
          public int getIVBClassVBPType()
          {
            typeSeek(8);
            return readInt();
          }
          
          public int getIVBClassVBPOff()
            throws DebugVC50WrongNumericTypeException
          {
            return readIntNumericLeafAt(12);
          }
          
          public int getIVBClassVBOff()
            throws DebugVC50WrongNumericTypeException
          {
            return readIntNumericLeafAt(12 + numericLeafLengthAt(12));
          }
          
          public short getEnumerateAttribute()
          {
            typeSeek(2);
            return readShort();
          }
          
          public long getEnumerateValue()
          {
            return readIntNumericLeafAt(4);
          }
          
          public String getEnumerateName()
          {
            return readLengthPrefixedStringAt(4 + numericLeafLengthAt(4));
          }
          
          public int getFriendFcnType()
          {
            typeSeek(4);
            return readInt();
          }
          
          public String getFriendFcnName()
          {
            return readLengthPrefixedStringAt(8);
          }
          
          public int getIndexValue()
          {
            typeSeek(4);
            return readInt();
          }
          
          public DebugVC50TypeIterator getIndexIterator()
          {
            int index = COFFFileParser.COFFFileImpl.COFFHeaderImpl.DebugVC50Impl.this.unbiasTypeIndex(getIndexValue());
            int offset = parent.getTypeOffset(index);
            return new DebugVC50TypeIteratorImpl(COFFFileParser.COFFFileImpl.COFFHeaderImpl.DebugVC50Impl.this, parent, base, numTypes, index, offset);
          }
          
          public short getMemberAttribute()
          {
            typeSeek(2);
            return readShort();
          }
          
          public int getMemberType()
          {
            typeSeek(4);
            return readInt();
          }
          
          public int getMemberOffset()
            throws DebugVC50WrongNumericTypeException
          {
            return readIntNumericLeafAt(8);
          }
          
          public String getMemberName()
          {
            return readLengthPrefixedStringAt(8 + numericLeafLengthAt(8));
          }
          
          public short getStaticAttribute()
          {
            typeSeek(2);
            return readShort();
          }
          
          public int getStaticType()
          {
            typeSeek(4);
            return readInt();
          }
          
          public String getStaticName()
          {
            return readLengthPrefixedStringAt(8);
          }
          
          public short getMethodCount()
          {
            typeSeek(2);
            return readShort();
          }
          
          public int getMethodList()
          {
            typeSeek(4);
            return readInt();
          }
          
          public String getMethodName()
          {
            return readLengthPrefixedStringAt(8);
          }
          
          public int getNestedType()
          {
            typeSeek(4);
            return readInt();
          }
          
          public String getNestedName()
          {
            return readLengthPrefixedStringAt(8);
          }
          
          public int getVFuncTabType()
          {
            typeSeek(4);
            return readInt();
          }
          
          public int getFriendClsType()
          {
            typeSeek(4);
            return readInt();
          }
          
          public short getOneMethodAttribute()
          {
            typeSeek(2);
            return readShort();
          }
          
          public int getOneMethodType()
          {
            typeSeek(4);
            return readInt();
          }
          
          public boolean isOneMethodIntroducingVirtual()
          {
            return isIntroducingVirtual(getOneMethodAttribute());
          }
          
          public int getOneMethodVBaseOff()
          {
            typeSeek(8);
            return readInt();
          }
          
          public String getOneMethodName()
          {
            int baseLen = 8 + (isOneMethodIntroducingVirtual() ? 4 : 0);
            return readLengthPrefixedStringAt(baseLen);
          }
          
          public int getVFuncOffType()
          {
            typeSeek(4);
            return readInt();
          }
          
          public int getVFuncOffOffset()
          {
            typeSeek(8);
            return readInt();
          }
          
          public short getNestedExAttribute()
          {
            typeSeek(2);
            return readShort();
          }
          
          public int getNestedExType()
          {
            typeSeek(4);
            return readInt();
          }
          
          public String getNestedExName()
          {
            return readLengthPrefixedStringAt(8);
          }
          
          public short getMemberModifyAttribute()
          {
            typeSeek(2);
            return readShort();
          }
          
          public int getMemberModifyType()
          {
            typeSeek(4);
            return readInt();
          }
          
          public String getMemberModifyName()
          {
            return readLengthPrefixedStringAt(8);
          }
          
          public short getNumericTypeAt(int byteOffset)
          {
            typeSeek(byteOffset);
            return readShort();
          }
          
          public int getNumericLengthAt(int byteOffset)
            throws DebugVC50WrongNumericTypeException
          {
            return numericLeafLengthAt(byteOffset);
          }
          
          public int getNumericIntAt(int byteOffset)
            throws DebugVC50WrongNumericTypeException
          {
            return readIntNumericLeafAt(byteOffset);
          }
          
          public long getNumericLongAt(int byteOffset)
            throws DebugVC50WrongNumericTypeException
          {
            throw new RuntimeException("Unimplemented");
          }
          
          public float getNumericFloatAt(int byteOffset)
            throws DebugVC50WrongNumericTypeException
          {
            throw new RuntimeException("Unimplemented");
          }
          
          public double getNumericDoubleAt(int byteOffset)
            throws DebugVC50WrongNumericTypeException
          {
            throw new RuntimeException("Unimplemented");
          }
          
          public byte[] getNumericDataAt(int byteOffset)
            throws DebugVC50WrongNumericTypeException
          {
            throw new RuntimeException("Unimplemented");
          }
          
          private void loadTypeRecord()
          {
            seek(typeRecordOffset);
            typeRecordSize = (readShort() & 0xFFFF);
            typeStringOffset = (typeRecordOffset + 2);
            loadTypeString();
          }
          
          private void loadTypeString()
          {
            seek(typeStringOffset);
            int lo = readByte() & 0xFF;
            if (lo >= 240)
            {
              typeStringLeaf = lo;
            }
            else
            {
              int hi = readByte() & 0xFF;
              typeStringLeaf = (hi << 8 | lo);
            }
          }
          
          private void typeSeek(int offset)
          {
            seek(typeStringOffset + offset);
          }
          
          private int typeStringLength()
          {
            if ((typeStringLeaf >= 240) && (typeStringLeaf <= 255)) {
              return typeStringLeaf - 240;
            }
            switch (typeStringLeaf)
            {
            case 4097: 
              return 8;
            case 4098: 
              int extraLen = 0;
              int attr = (getPointerAttributes() & 0x1F) >> 0;
              int mode = (getPointerAttributes() & 0xE0) >> 5;
              if (attr == 8) {
                extraLen = 4 + numericLeafLengthAt(typeStringOffset + 14);
              } else if ((mode == 2) || (mode == 3)) {
                extraLen = 6;
              }
              return 10 + extraLen;
            case 4099: 
              int temp = 10 + numericLeafLengthAt(10);
              return temp + lengthPrefixedStringLengthAt(temp);
            case 4100: 
            case 4101: 
              int temp = 18 + numericLeafLengthAt(18);
              return temp + lengthPrefixedStringLengthAt(temp);
            case 4102: 
              int temp = 10 + numericLeafLengthAt(10);
              return temp + lengthPrefixedStringLengthAt(temp);
            case 4103: 
              return 14 + lengthPrefixedStringLengthAt(14);
            case 4104: 
              return 14;
            case 4105: 
              return 26;
            case 10: 
              return 4 + (getVTShapeCount() + 1) / 2;
            case 12: 
            case 4106: 
              throw new COFFException("COBOL symbols unimplemented");
            case 4107: 
              return 6;
            case 14: 
              return 4;
            case 15: 
              return 2;
            case 16: 
              return 2;
            case 4108: 
              return 10 + lengthPrefixedStringLengthAt(10);
            case 4109: 
              return 6 + 4 * getVFTPathCount();
            case 4110: 
              return 14 + lengthPrefixedStringLengthAt(14);
            case 20: 
              return 6;
            case 4111: 
              throw new COFFException("OEM symbols unimplemented");
            case 22: 
              return 10 + lengthPrefixedStringLengthAt(10);
            case 4608: 
              return 6 + numericLeafLengthAt(6);
            case 4609: 
              return 6 + 4 * getArgListCount();
            case 4610: 
              return 6 + lengthPrefixedStringLengthAt(6);
            case 4611: 
              return 2;
            case 4612: 
              return 6 + 4 * getDerivedCount();
            case 4613: 
              return 8;
            case 4614: 
              return 6 + 4 * getMListLength() + (isMListIntroducingVirtual() ? 4 : 0);
            case 4615: 
            case 4616: 
            case 4617: 
            case 4618: 
              throw new COFFException("LF_DIMCONU, LF_DIMCONLU, LF_DIMVARU, and LF_DIMVARLU unsupported");
            case 524: 
              seek(typeStringOffset + 2);
              return 4 + readShort();
            case 5120: 
              return 8 + numericLeafLengthAt(8);
            case 5121: 
            case 5122: 
              int temp = 12 + numericLeafLengthAt(12);
              return temp + numericLeafLengthAt(temp);
            case 1027: 
              int temp = 4 + numericLeafLengthAt(4);
              return temp + lengthPrefixedStringLengthAt(temp);
            case 5123: 
              return 8 + lengthPrefixedStringLengthAt(8);
            case 5124: 
              return 8;
            case 5125: 
              int temp = 8 + numericLeafLengthAt(8);
              return temp + lengthPrefixedStringLengthAt(temp);
            case 5126: 
              return 8 + lengthPrefixedStringLengthAt(8);
            case 5127: 
              return 8 + lengthPrefixedStringLengthAt(8);
            case 5128: 
              return 8 + lengthPrefixedStringLengthAt(8);
            case 5129: 
              return 8;
            case 5130: 
              return 8;
            case 5131: 
              int baseLen = 8 + (isOneMethodIntroducingVirtual() ? 4 : 0);
              return baseLen + lengthPrefixedStringLengthAt(baseLen);
            case 5132: 
              return 12;
            case 5133: 
              return 8 + lengthPrefixedStringLengthAt(8);
            case 5134: 
              return 8 + lengthPrefixedStringLengthAt(8);
            case 32768: 
            case 32769: 
            case 32770: 
            case 32771: 
            case 32772: 
            case 32773: 
            case 32774: 
            case 32775: 
            case 32776: 
            case 32777: 
            case 32778: 
            case 32779: 
            case 32780: 
            case 32781: 
            case 32782: 
            case 32783: 
            case 32784: 
              throw new RuntimeException("Unexpected numeric leaf " + typeStringLeaf + "in type string");
            }
            throw new COFFException("Unrecognized leaf " + typeStringLeaf + " in type string at offset " + typeStringOffset);
          }
          
          private boolean isIntroducingVirtual(int mprop)
          {
            int masked = mprop & 0x1C;
            return (masked == 16) || (masked == 24);
          }
          
          private int numericLeafLengthAt(int offset)
          {
            return COFFFileParser.COFFFileImpl.COFFHeaderImpl.DebugVC50Impl.this.numericLeafLengthAt(typeStringOffset + offset);
          }
          
          private int readIntNumericLeafAt(int offset)
          {
            return COFFFileParser.COFFFileImpl.COFFHeaderImpl.DebugVC50Impl.this.readIntNumericLeafAt(typeStringOffset + offset);
          }
          
          private int lengthPrefixedStringLengthAt(int offset)
          {
            return COFFFileParser.COFFFileImpl.COFFHeaderImpl.DebugVC50Impl.this.lengthPrefixedStringLengthAt(typeStringOffset + offset);
          }
          
          private String readLengthPrefixedStringAt(int offset)
          {
            return COFFFileParser.COFFFileImpl.COFFHeaderImpl.DebugVC50Impl.this.readLengthPrefixedStringAt(typeStringOffset + offset);
          }
        }
        
        private int numericLeafLengthAt(int absoluteOffset)
          throws DebugVC50WrongNumericTypeException
        {
          seek(absoluteOffset);
          int leaf = readShort() & 0xFFFF;
          if (leaf < 32768) {
            return 2;
          }
          switch (leaf)
          {
          case 32768: 
            return 3;
          case 32769: 
          case 32770: 
            return 4;
          case 32771: 
          case 32772: 
            return 6;
          case 32773: 
            return 6;
          case 32774: 
            return 10;
          case 32775: 
            return 12;
          case 32776: 
            return 18;
          case 32777: 
          case 32778: 
            return 18;
          case 32779: 
            return 8;
          case 32780: 
            return 10;
          case 32781: 
            return 18;
          case 32782: 
            return 26;
          case 32783: 
            return 66;
          case 32784: 
            return 4 + readIntNumericLeafAt(absoluteOffset + 2);
          }
          throw new DebugVC50WrongNumericTypeException("Illegal numeric leaf index " + leaf + " at offset " + absoluteOffset);
        }
        
        private int readIntNumericLeafAt(int absoluteOffset)
          throws DebugVC50WrongNumericTypeException
        {
          seek(absoluteOffset);
          int leaf = readShort() & 0xFFFF;
          if (leaf < 32768) {
            return leaf;
          }
          switch (leaf)
          {
          case 32768: 
            return readByte() & 0xFF;
          case 32769: 
          case 32770: 
            return readShort() & 0xFFFF;
          case 32771: 
          case 32772: 
            return readInt();
          }
          throw new DebugVC50WrongNumericTypeException("Illegal numeric leaf index " + leaf);
        }
        
        private long readLongNumericLeafAt(int absoluteOffset)
          throws DebugVC50WrongNumericTypeException
        {
          seek(absoluteOffset);
          int leaf = readShort() & 0xFFFF;
          if (leaf < 32768) {
            return leaf;
          }
          switch (leaf)
          {
          case 32768: 
            return readByte() & 0xFF;
          case 32769: 
          case 32770: 
            return readShort() & 0xFFFF;
          case 32771: 
          case 32772: 
            return readInt() & 0xFFFFFFFF;
          case 32777: 
          case 32778: 
            return readLong();
          }
          throw new DebugVC50WrongNumericTypeException("Illegal numeric leaf index " + leaf);
        }
        
        private float readFloatNumericLeafAt(int absoluteOffset)
          throws DebugVC50WrongNumericTypeException
        {
          seek(absoluteOffset);
          int leaf = readShort() & 0xFFFF;
          if (leaf != 32773) {
            throw new DebugVC50WrongNumericTypeException("Illegal numeric leaf index " + leaf);
          }
          return readFloat();
        }
        
        private double readDoubleNumericLeafAt(int absoluteOffset)
          throws DebugVC50WrongNumericTypeException
        {
          seek(absoluteOffset);
          int leaf = readShort() & 0xFFFF;
          if (leaf != 32774) {
            throw new DebugVC50WrongNumericTypeException("Illegal numeric leaf index " + leaf);
          }
          return readDouble();
        }
        
        private int lengthPrefixedStringLengthAt(int absoluteOffset)
        {
          seek(absoluteOffset);
          int len = readByte() & 0xFF;
          return 1 + len;
        }
        
        private String readLengthPrefixedStringAt(int absoluteOffset)
        {
          seek(absoluteOffset);
          int len = readByte() & 0xFF;
          byte[] res = new byte[len];
          int numRead = readBytes(res);
          if (numRead != len) {
            throw new COFFException("Error reading length prefixed string in symbol at offset " + absoluteOffset);
          }
          try
          {
            return new String(res, "US-ASCII");
          }
          catch (UnsupportedEncodingException e)
          {
            throw new COFFException(e);
          }
        }
        
        private int unbiasTypeIndex(int index)
        {
          return index - 4096;
        }
        
        private int biasTypeIndex(int index)
        {
          return index + 4096;
        }
      }
      
      class SectionHeaderImpl
        implements SectionHeader
      {
        private String name;
        private int virtualSize;
        private int virtualAddress;
        private int sizeOfRawData;
        private int pointerToRawData;
        private int pointerToRelocations;
        private int pointerToLineNumbers;
        private short numberOfRelocations;
        private short numberOfLineNumbers;
        private int characteristics;
        private MemoizedObject[] relocations;
        private MemoizedObject[] lineNumbers;
        
        public SectionHeaderImpl(int offset)
          throws COFFException
        {
          seek(offset);
          
          byte[] tmpName = new byte[8];
          int numRead = readBytes(tmpName);
          if (numRead != 8) {
            throw new COFFException("Error reading name of section header at offset " + offset);
          }
          if (tmpName[0] == 47)
          {
            int index = 0;
            try
            {
              index = Integer.parseInt(new String(tmpName, 1, tmpName.length - 1, "US-ASCII"));
            }
            catch (NumberFormatException e)
            {
              throw new COFFException("Error parsing string table index of name of section header at offset " + offset);
            }
            catch (UnsupportedEncodingException e)
            {
              throw new COFFException(e);
            }
            name = getStringTable().get(index);
          }
          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);
      }
  
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