using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.IO;
|
|
using System.Text;
|
|
using Hack.Tools.Common;
|
|
|
|
namespace Hack.Xenosaga.Process
|
|
{
|
|
public class evtClass
|
|
{
|
|
public struct stFile
|
|
{
|
|
public UInt32 namePos;
|
|
public UInt32 nameLength;
|
|
public UInt32 filePos;
|
|
public UInt32 fileLength;
|
|
public string name;
|
|
public byte[] file;
|
|
}
|
|
|
|
public UInt32 id { get; private set; }
|
|
public UInt16 unkAdr4 { get; private set; }
|
|
public UInt16 unkAdr6 { get; private set; }
|
|
public int fileSize { get; private set; }
|
|
public int adrNames { get; private set; }
|
|
public UInt16 unkAdr16 { get; private set; }
|
|
public int nbFiles { get; private set; }
|
|
public List<stFile> listFiles { get; private set; }
|
|
|
|
#region Constructors
|
|
|
|
public evtClass()
|
|
{ }
|
|
|
|
public evtClass(string pathName)
|
|
{
|
|
init(pathName);
|
|
}
|
|
|
|
public evtClass(BinaryReader br)
|
|
{
|
|
init(br);
|
|
}
|
|
|
|
~evtClass()
|
|
{ }
|
|
|
|
#endregion
|
|
|
|
#region Privates methods
|
|
|
|
private byte[] readFileBytes(BinaryReader br, long pos, int size)
|
|
{
|
|
byte[] file;
|
|
long posSave = br.BaseStream.Position;
|
|
|
|
br.BaseStream.Position = pos;
|
|
|
|
file = br.ReadBytes(size);
|
|
|
|
br.BaseStream.Position = posSave;
|
|
|
|
return file;
|
|
}
|
|
|
|
private string readFileName(BinaryReader br, long pos, int size)
|
|
{
|
|
string name = "";
|
|
long posSave = br.BaseStream.Position;
|
|
|
|
br.BaseStream.Position = pos;
|
|
|
|
name = br.BytestoStringAscii(size);
|
|
|
|
br.BaseStream.Position = posSave;
|
|
|
|
return name;
|
|
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Publics methods
|
|
|
|
/// <summary>
|
|
/// Init an evt file (archive)
|
|
/// </summary>
|
|
/// <param name="pathName">Path of the file</param>
|
|
/// <returns></returns>
|
|
public bool init(string pathName)
|
|
{
|
|
bool result = true;
|
|
|
|
using (BinaryReader br = new BinaryReader(File.Open(pathName, FileMode.Open)))
|
|
{
|
|
result = init(br);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Init an evt file (archive)
|
|
/// </summary>
|
|
/// <param name="br">BinaryReader of the file</param>
|
|
/// <returns></returns>
|
|
public bool init(BinaryReader br)
|
|
{
|
|
listFiles = new List<stFile>();
|
|
|
|
id = br.ReadUInt32();
|
|
if (id != 0x30304C46)
|
|
{
|
|
Trace.WriteLine("ERROR : Not a valid evt file");
|
|
return false;
|
|
}
|
|
|
|
unkAdr4 = br.ReadUInt16();
|
|
unkAdr6 = br.ReadUInt16();
|
|
fileSize = br.ReadInt32();
|
|
adrNames = br.ReadInt32();
|
|
unkAdr16 = br.ReadUInt16();
|
|
nbFiles = br.ReadInt16();
|
|
|
|
for (int i = 0; i < nbFiles; i++)
|
|
{
|
|
stFile st = new stFile();
|
|
|
|
st.namePos = br.ReadUInt32();
|
|
st.nameLength = br.ReadUInt32();
|
|
st.name = readFileName(br, (long)st.namePos, (int)st.nameLength);
|
|
|
|
st.filePos = br.ReadUInt32();
|
|
st.fileLength = br.ReadUInt32();
|
|
st.file = readFileBytes(br, (long)st.filePos, (int)st.fileLength);
|
|
|
|
listFiles.Add(st);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
|
|
public class JavaClass
|
|
{
|
|
public interface iCONSTANT
|
|
{
|
|
byte tag { get; set; }
|
|
}
|
|
|
|
private class CONSTANT_Class_info : iCONSTANT
|
|
{
|
|
private byte _tag;
|
|
public Int16 name_index;
|
|
|
|
public CONSTANT_Class_info(byte tag)
|
|
{
|
|
_tag = tag;
|
|
}
|
|
|
|
public byte tag { get { return _tag; } set { _tag = value; } }
|
|
}
|
|
|
|
private class CONSTANT_Fieldref_info : iCONSTANT
|
|
{
|
|
private byte _tag;
|
|
public Int16 class_index;
|
|
public Int16 name_and_type_index;
|
|
|
|
public CONSTANT_Fieldref_info(byte tag)
|
|
{
|
|
_tag = tag;
|
|
}
|
|
|
|
public byte tag { get { return _tag; } set { _tag = value; } }
|
|
}
|
|
|
|
private class CONSTANT_Methodref_info : iCONSTANT
|
|
{
|
|
private byte _tag;
|
|
public Int16 class_index;
|
|
public Int16 name_and_type_index;
|
|
|
|
public CONSTANT_Methodref_info(byte tag)
|
|
{
|
|
_tag = tag;
|
|
}
|
|
|
|
public byte tag { get { return _tag; } set { _tag = value; } }
|
|
}
|
|
|
|
private class CONSTANT_InterfaceMethodref_info : iCONSTANT
|
|
{
|
|
private byte _tag;
|
|
public Int16 class_index;
|
|
public Int16 name_and_type_index;
|
|
|
|
public CONSTANT_InterfaceMethodref_info(byte tag)
|
|
{
|
|
_tag = tag;
|
|
}
|
|
|
|
public byte tag { get { return _tag; } set { _tag = value; } }
|
|
}
|
|
|
|
private class CONSTANT_String_info : iCONSTANT
|
|
{
|
|
private byte _tag;
|
|
public Int16 string_index;
|
|
|
|
public CONSTANT_String_info(byte tag)
|
|
{
|
|
_tag = tag;
|
|
}
|
|
|
|
public byte tag { get { return _tag; } set { _tag = value; } }
|
|
}
|
|
|
|
private class CONSTANT_Integer_info : iCONSTANT
|
|
{
|
|
private byte _tag;
|
|
public Int32 bytes;
|
|
|
|
public CONSTANT_Integer_info(byte tag)
|
|
{
|
|
_tag = tag;
|
|
}
|
|
|
|
public byte tag { get { return _tag; } set { _tag = value; } }
|
|
}
|
|
|
|
private class CONSTANT_Float_info : iCONSTANT
|
|
{
|
|
private byte _tag;
|
|
public Int32 bytes;
|
|
|
|
public CONSTANT_Float_info(byte tag)
|
|
{
|
|
_tag = tag;
|
|
}
|
|
|
|
public byte tag { get { return _tag; } set { _tag = value; } }
|
|
}
|
|
|
|
private class CONSTANT_Long_info : iCONSTANT
|
|
{
|
|
private byte _tag;
|
|
public Int32 high_bytes;
|
|
public Int32 low_bytes;
|
|
|
|
public CONSTANT_Long_info(byte tag)
|
|
{
|
|
_tag = tag;
|
|
}
|
|
|
|
public byte tag { get { return _tag; } set { _tag = value; } }
|
|
}
|
|
|
|
private class CONSTANT_Double_info : iCONSTANT
|
|
{
|
|
private byte _tag;
|
|
public Int32 high_bytes;
|
|
public Int32 low_bytes;
|
|
|
|
public CONSTANT_Double_info(byte tag)
|
|
{
|
|
_tag = tag;
|
|
}
|
|
|
|
public byte tag { get { return _tag; } set { _tag = value; } }
|
|
}
|
|
|
|
private class CONSTANT_NameAndType_info : iCONSTANT
|
|
{
|
|
private byte _tag;
|
|
public Int16 name_index;
|
|
public Int16 descriptor_index;
|
|
|
|
public CONSTANT_NameAndType_info(byte tag)
|
|
{
|
|
_tag = tag;
|
|
}
|
|
|
|
public byte tag { get { return _tag; } set { _tag = value; } }
|
|
}
|
|
|
|
private class CONSTANT_Utf8_info : iCONSTANT
|
|
{
|
|
private byte _tag;
|
|
public Int16 length { get; set; }
|
|
public byte[] bytes { get; set; }
|
|
|
|
public CONSTANT_Utf8_info(byte tag)
|
|
{
|
|
_tag = tag;
|
|
}
|
|
|
|
public byte tag { get { return _tag; } set { _tag = value; } }
|
|
}
|
|
|
|
private class CONSTANT_MethodHandle_info : iCONSTANT
|
|
{
|
|
private byte _tag;
|
|
public byte reference_kind;
|
|
public Int16 reference_index;
|
|
|
|
public CONSTANT_MethodHandle_info(byte tag)
|
|
{
|
|
_tag = tag;
|
|
}
|
|
|
|
public byte tag { get { return _tag; } set { _tag = value; } }
|
|
}
|
|
|
|
private class CONSTANT_MethodType_info : iCONSTANT
|
|
{
|
|
private byte _tag;
|
|
public Int16 descriptor_index;
|
|
|
|
public CONSTANT_MethodType_info(byte tag)
|
|
{
|
|
_tag = tag;
|
|
}
|
|
|
|
public byte tag { get { return _tag; } set { _tag = value; } }
|
|
}
|
|
|
|
private class CONSTANT_InvokeDynamic_info : iCONSTANT
|
|
{
|
|
private byte _tag;
|
|
public Int16 bootstrap_method_attr_index;
|
|
public Int16 name_and_type_index;
|
|
|
|
public CONSTANT_InvokeDynamic_info(byte tag)
|
|
{
|
|
_tag = tag;
|
|
}
|
|
|
|
public byte tag { get { return _tag; } set { _tag = value; } }
|
|
}
|
|
|
|
private struct stField
|
|
{
|
|
public Int16 access_flags;
|
|
public Int16 name_index;
|
|
public Int16 descriptor_index;
|
|
public Int16 attributes_count;
|
|
public Dictionary<int, stAttribut> attributes;
|
|
}
|
|
|
|
private struct stMethod
|
|
{
|
|
public Int16 access_flags;
|
|
public Int16 name_index;
|
|
public Int16 descriptor_index;
|
|
public Int16 attributes_count;
|
|
public Dictionary<int, stAttribut> attributes;
|
|
}
|
|
|
|
private struct stAttribut
|
|
{
|
|
public Int16 attribute_name_index;
|
|
public long attribute_length;
|
|
public byte[] info;
|
|
public List<stOpcode> infoString;
|
|
}
|
|
|
|
private struct stOpcode
|
|
{
|
|
public byte opcode;
|
|
public string name;
|
|
public string type;
|
|
public string src_t;
|
|
public string dst_t;
|
|
public int value;
|
|
public int value2;
|
|
public int index;
|
|
public int count;
|
|
public int zero;
|
|
public int jumptarget;
|
|
public int dim;
|
|
}
|
|
|
|
private byte[] magic;
|
|
private Int16 minor_version;
|
|
private Int16 major_version;
|
|
private Int16 constant_pool_count;
|
|
private Dictionary<int, iCONSTANT> constant_pool;
|
|
private Int16 access_flags;
|
|
private Int16 this_class;
|
|
private Int16 super_class;
|
|
private Int16 interfaces_count;
|
|
private List<Int16> interfaces;
|
|
private Int16 fields_count;
|
|
private Dictionary<int, stField> fields;
|
|
private Int16 methods_count;
|
|
private Dictionary<int, stMethod> methods;
|
|
private Int16 attributes_count;
|
|
private Dictionary<int, stAttribut> attributes;
|
|
|
|
//---------------------------------------------------------------------
|
|
|
|
#region Constructors
|
|
|
|
public JavaClass()
|
|
{ }
|
|
|
|
~JavaClass()
|
|
{ }
|
|
|
|
#endregion
|
|
|
|
//---------------------------------------------------------------------
|
|
|
|
#region Compilation
|
|
|
|
private void compilConstants(BinaryWriter bw)
|
|
{
|
|
foreach (KeyValuePair<int, iCONSTANT> constant in constant_pool)
|
|
{
|
|
bw.Write(constant.Value.tag);
|
|
|
|
switch (constant.Value.tag)
|
|
{
|
|
case 1:
|
|
CONSTANT_Utf8_info stUtf8 = (CONSTANT_Utf8_info)constant.Value;
|
|
bw.Write(IntToByteArrayBE(stUtf8.length, 2), 0, 2);
|
|
bw.Write(stUtf8.bytes);
|
|
break;
|
|
|
|
case 3:
|
|
CONSTANT_Integer_info stInteger = (CONSTANT_Integer_info)constant.Value;
|
|
bw.Write(IntToByteArrayBE(stInteger.bytes), 0, 4);
|
|
break;
|
|
|
|
case 4:
|
|
CONSTANT_Float_info stFloat = (CONSTANT_Float_info)constant.Value;
|
|
bw.Write(IntToByteArrayBE(stFloat.bytes), 0, 4);
|
|
break;
|
|
|
|
case 5:
|
|
CONSTANT_Long_info stLong = (CONSTANT_Long_info)constant.Value;
|
|
bw.Write(stLong.high_bytes);
|
|
bw.Write(stLong.low_bytes);
|
|
break;
|
|
|
|
case 6:
|
|
CONSTANT_Double_info stDouble = (CONSTANT_Double_info)constant.Value;
|
|
bw.Write(stDouble.high_bytes);
|
|
bw.Write(stDouble.low_bytes);
|
|
break;
|
|
|
|
case 7:
|
|
CONSTANT_Class_info stClass = (CONSTANT_Class_info)constant.Value;
|
|
bw.Write(IntToByteArrayBE(stClass.name_index, 2), 0, 2);
|
|
break;
|
|
|
|
case 8:
|
|
CONSTANT_String_info stString = (CONSTANT_String_info)constant.Value;
|
|
bw.Write(IntToByteArrayBE(stString.string_index, 2), 0, 2);
|
|
break;
|
|
|
|
case 9:
|
|
CONSTANT_Fieldref_info stFieldref = (CONSTANT_Fieldref_info)constant.Value;
|
|
bw.Write(IntToByteArrayBE(stFieldref.class_index, 2), 0, 2);
|
|
bw.Write(IntToByteArrayBE(stFieldref.name_and_type_index, 2), 0, 2);
|
|
break;
|
|
|
|
case 10:
|
|
CONSTANT_Methodref_info stMethodref = (CONSTANT_Methodref_info)constant.Value;
|
|
bw.Write(IntToByteArrayBE(stMethodref.class_index, 2), 0, 2);
|
|
bw.Write(IntToByteArrayBE(stMethodref.name_and_type_index, 2), 0, 2);
|
|
break;
|
|
|
|
case 11:
|
|
CONSTANT_InterfaceMethodref_info stInterfaceMethodref = (CONSTANT_InterfaceMethodref_info)constant.Value;
|
|
bw.Write(IntToByteArrayBE(stInterfaceMethodref.class_index, 2), 0, 2);
|
|
bw.Write(IntToByteArrayBE(stInterfaceMethodref.name_and_type_index, 2), 0, 2);
|
|
break;
|
|
|
|
case 12:
|
|
CONSTANT_NameAndType_info stNameAndType = (CONSTANT_NameAndType_info)constant.Value;
|
|
bw.Write(IntToByteArrayBE(stNameAndType.name_index, 2), 0, 2);
|
|
bw.Write(IntToByteArrayBE(stNameAndType.descriptor_index, 2), 0, 2);
|
|
break;
|
|
|
|
case 15:
|
|
CONSTANT_MethodHandle_info stMethodHandle = (CONSTANT_MethodHandle_info)constant.Value;
|
|
bw.Write(stMethodHandle.reference_kind);
|
|
bw.Write(IntToByteArrayBE(stMethodHandle.reference_index, 2), 0, 2);
|
|
break;
|
|
|
|
case 16:
|
|
CONSTANT_MethodType_info stMethodType = (CONSTANT_MethodType_info)constant.Value;
|
|
bw.Write(IntToByteArrayBE(stMethodType.descriptor_index, 2), 0, 2);
|
|
break;
|
|
|
|
case 18:
|
|
CONSTANT_InvokeDynamic_info stInvokeDynamic = (CONSTANT_InvokeDynamic_info)constant.Value;
|
|
bw.Write(IntToByteArrayBE(stInvokeDynamic.bootstrap_method_attr_index, 2), 0, 2);
|
|
bw.Write(IntToByteArrayBE(stInvokeDynamic.name_and_type_index, 2), 0, 2);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void compilInterfaces(BinaryWriter bw)
|
|
{
|
|
foreach (Int16 index in interfaces)
|
|
{
|
|
bw.Write(IntToByteArrayBE(index, 2), 0, 2);
|
|
}
|
|
}
|
|
|
|
private void compilFields(BinaryWriter bw)
|
|
{
|
|
foreach (KeyValuePair<int, stField> field in fields)
|
|
{
|
|
bw.Write(IntToByteArrayBE(field.Value.access_flags, 2), 0, 2);
|
|
bw.Write(IntToByteArrayBE(field.Value.name_index, 2), 0, 2);
|
|
bw.Write(IntToByteArrayBE(field.Value.descriptor_index, 2), 0, 2);
|
|
bw.Write(IntToByteArrayBE(field.Value.attributes_count, 2), 0, 2);
|
|
|
|
if (field.Value.attributes_count > 0)
|
|
{
|
|
foreach (KeyValuePair<int, stAttribut> attribut in field.Value.attributes)
|
|
{
|
|
bw.Write(IntToByteArrayBE(attribut.Value.attribute_name_index, 2), 0, 2);
|
|
bw.Write(IntToByteArrayBE((int)attribut.Value.attribute_length, 2), 0, 2);
|
|
bw.Write(attribut.Value.info);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void compilMethods(BinaryWriter bw)
|
|
{
|
|
foreach (KeyValuePair<int, stMethod> method in methods)
|
|
{
|
|
bw.Write(IntToByteArrayBE(method.Value.access_flags, 2), 0, 2);
|
|
bw.Write(IntToByteArrayBE(method.Value.name_index, 2), 0, 2);
|
|
bw.Write(IntToByteArrayBE(method.Value.descriptor_index, 2), 0, 2);
|
|
bw.Write(IntToByteArrayBE(method.Value.attributes_count, 2), 0, 2);
|
|
|
|
if (method.Value.attributes_count > 0)
|
|
{
|
|
foreach (KeyValuePair<int, stAttribut> attribut in method.Value.attributes)
|
|
{
|
|
bw.Write(IntToByteArrayBE(attribut.Value.attribute_name_index, 2), 0, 2);
|
|
bw.Write(IntToByteArrayBE((int)attribut.Value.attribute_length, 4), 0, 4);
|
|
|
|
if (attribut.Value.attribute_length > 0)
|
|
bw.Write(attribut.Value.info);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void compilAttributes(BinaryWriter bw)
|
|
{
|
|
foreach (KeyValuePair<int, stAttribut> attribut in attributes)
|
|
{
|
|
bw.Write(IntToByteArrayBE(attribut.Value.attribute_name_index, 2), 0, 2);
|
|
bw.Write(IntToByteArrayBE((int)attribut.Value.attribute_length, 4), 0, 4);
|
|
|
|
if (attribut.Value.attribute_length > 0)
|
|
bw.Write(attribut.Value.info);
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Get data
|
|
|
|
private string getConstantValue(Int16 index, bool replace = false)
|
|
{
|
|
string value = "";
|
|
|
|
byte tag = constant_pool[index].tag;
|
|
|
|
switch (tag)
|
|
{
|
|
case 1:
|
|
CONSTANT_Utf8_info stUtf8 = (CONSTANT_Utf8_info)constant_pool[index];
|
|
|
|
if (stUtf8.length > 0)
|
|
{
|
|
if (replace)
|
|
value = Encoding.UTF8.GetString(stUtf8.bytes).Replace("\n", "\\n");
|
|
else
|
|
value = Encoding.UTF8.GetString(stUtf8.bytes);
|
|
}
|
|
break;
|
|
|
|
case 3:
|
|
CONSTANT_Integer_info stInteger = (CONSTANT_Integer_info)constant_pool[index];
|
|
|
|
value = string.Format("{0:D}", stInteger.bytes);
|
|
break;
|
|
|
|
case 4:
|
|
CONSTANT_Float_info stFloat = (CONSTANT_Float_info)constant_pool[index];
|
|
|
|
value = BitConverter.ToSingle(BitConverter.GetBytes(stFloat.bytes), 0).ToString();
|
|
break;
|
|
|
|
case 5:
|
|
CONSTANT_Long_info stLong = (CONSTANT_Long_info)constant_pool[index];
|
|
|
|
value = (((long)stLong.high_bytes << 32) + stLong.low_bytes).ToString();
|
|
break;
|
|
|
|
case 6:
|
|
CONSTANT_Double_info stDouble = (CONSTANT_Double_info)constant_pool[index];
|
|
|
|
value = BitConverter.ToDouble(BitConverter.GetBytes(((long)stDouble.high_bytes << 32) + stDouble.low_bytes), 0).ToString();
|
|
break;
|
|
|
|
case 7:
|
|
CONSTANT_Class_info stClass = (CONSTANT_Class_info)constant_pool[index];
|
|
|
|
value = getConstantValue(stClass.name_index);
|
|
break;
|
|
|
|
case 8:
|
|
CONSTANT_String_info stString = (CONSTANT_String_info)constant_pool[index];
|
|
|
|
value = getConstantValue(stString.string_index);
|
|
break;
|
|
|
|
case 9:
|
|
CONSTANT_Fieldref_info stFieldref = (CONSTANT_Fieldref_info)constant_pool[index];
|
|
|
|
value = getConstantValue(stFieldref.class_index) + getConstantValue(stFieldref.name_and_type_index);
|
|
break;
|
|
|
|
case 10:
|
|
CONSTANT_Methodref_info stMethodref = (CONSTANT_Methodref_info)constant_pool[index];
|
|
|
|
value = getConstantValue(stMethodref.class_index) + getConstantValue(stMethodref.name_and_type_index);
|
|
break;
|
|
|
|
case 11:
|
|
CONSTANT_InterfaceMethodref_info stInterfaceMethodref = (CONSTANT_InterfaceMethodref_info)constant_pool[index];
|
|
|
|
value = getConstantValue(stInterfaceMethodref.class_index) + getConstantValue(stInterfaceMethodref.name_and_type_index);
|
|
break;
|
|
|
|
case 12:
|
|
CONSTANT_NameAndType_info stNameAndType = (CONSTANT_NameAndType_info)constant_pool[index];
|
|
|
|
value = getConstantValue(stNameAndType.name_index) + getConstantValue(stNameAndType.descriptor_index);
|
|
break;
|
|
|
|
case 15:
|
|
CONSTANT_MethodHandle_info stMethodHandle = (CONSTANT_MethodHandle_info)constant_pool[index];
|
|
|
|
value = getConstantValue(stMethodHandle.reference_index);
|
|
break;
|
|
|
|
case 16:
|
|
CONSTANT_MethodType_info stMethodType = (CONSTANT_MethodType_info)constant_pool[index];
|
|
|
|
value = getConstantValue(stMethodType.descriptor_index);
|
|
break;
|
|
|
|
case 18:
|
|
CONSTANT_InvokeDynamic_info stInvokeDynamic = (CONSTANT_InvokeDynamic_info)constant_pool[index];
|
|
|
|
value = getConstantValue(stInvokeDynamic.bootstrap_method_attr_index) + getConstantValue(stInvokeDynamic.name_and_type_index);
|
|
break;
|
|
}
|
|
|
|
return value;
|
|
}
|
|
|
|
private byte[] getConstantBytes(Int16 index)
|
|
{
|
|
byte tag = constant_pool[index].tag;
|
|
|
|
switch (tag)
|
|
{
|
|
case 1:
|
|
CONSTANT_Utf8_info stUtf8 = (CONSTANT_Utf8_info)constant_pool[index];
|
|
|
|
if (stUtf8.length > 0)
|
|
return stUtf8.bytes;
|
|
break;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Read data
|
|
|
|
private void readConstants(BinaryReader br)
|
|
{
|
|
constant_pool = new Dictionary<int, iCONSTANT>();
|
|
|
|
constant_pool_count = br.ReadInt16BE();
|
|
constant_pool_count--;
|
|
|
|
for (int i = 1; i < constant_pool_count+1; i++)
|
|
{
|
|
byte tag = br.ReadByte();
|
|
|
|
switch (tag)
|
|
{
|
|
case 1:
|
|
CONSTANT_Utf8_info cUtf8 = new CONSTANT_Utf8_info(tag);
|
|
cUtf8.length = br.ReadInt16BE();
|
|
if (cUtf8.length > 0)
|
|
cUtf8.bytes = br.ReadBytes(cUtf8.length);
|
|
constant_pool.Add(i, cUtf8);
|
|
break;
|
|
|
|
case 3:
|
|
CONSTANT_Integer_info cInteger = new CONSTANT_Integer_info(tag);
|
|
cInteger.bytes = br.ReadInt32BE();
|
|
constant_pool.Add(i, cInteger);
|
|
break;
|
|
|
|
case 4:
|
|
CONSTANT_Float_info cFloat = new CONSTANT_Float_info(tag);
|
|
cFloat.bytes = br.ReadInt32BE();
|
|
constant_pool.Add(i, cFloat);
|
|
break;
|
|
|
|
case 5:
|
|
CONSTANT_Long_info cLong = new CONSTANT_Long_info(tag);
|
|
cLong.high_bytes = br.ReadInt32BE();
|
|
cLong.low_bytes = br.ReadInt32BE();
|
|
constant_pool.Add(i, cLong);
|
|
break;
|
|
|
|
case 6:
|
|
CONSTANT_Double_info cDouble = new CONSTANT_Double_info(tag);
|
|
cDouble.high_bytes = br.ReadInt32BE();
|
|
cDouble.low_bytes = br.ReadInt32BE();
|
|
constant_pool.Add(i, cDouble);
|
|
break;
|
|
|
|
case 7:
|
|
CONSTANT_Class_info cClass = new CONSTANT_Class_info(tag);
|
|
cClass.name_index = br.ReadInt16BE();
|
|
constant_pool.Add(i, cClass);
|
|
break;
|
|
|
|
case 8:
|
|
CONSTANT_String_info cString = new CONSTANT_String_info(tag);
|
|
cString.string_index = br.ReadInt16BE();
|
|
constant_pool.Add(i, cString);
|
|
break;
|
|
|
|
case 9:
|
|
CONSTANT_Fieldref_info cFieldref = new CONSTANT_Fieldref_info(tag);
|
|
cFieldref.class_index = br.ReadInt16BE();
|
|
cFieldref.name_and_type_index = br.ReadInt16BE();
|
|
constant_pool.Add(i, cFieldref);
|
|
break;
|
|
|
|
case 10:
|
|
CONSTANT_Methodref_info cMethodref = new CONSTANT_Methodref_info(tag);
|
|
cMethodref.class_index = br.ReadInt16BE();
|
|
cMethodref.name_and_type_index = br.ReadInt16BE();
|
|
constant_pool.Add(i, cMethodref);
|
|
break;
|
|
|
|
case 11:
|
|
CONSTANT_InterfaceMethodref_info cInterfaceMethodref = new CONSTANT_InterfaceMethodref_info(tag);
|
|
cInterfaceMethodref.class_index = br.ReadInt16BE();
|
|
cInterfaceMethodref.name_and_type_index = br.ReadInt16BE();
|
|
constant_pool.Add(i, cInterfaceMethodref);
|
|
break;
|
|
|
|
case 12:
|
|
CONSTANT_NameAndType_info cNameAndType = new CONSTANT_NameAndType_info(tag);
|
|
cNameAndType.name_index = br.ReadInt16BE();
|
|
cNameAndType.descriptor_index = br.ReadInt16BE();
|
|
constant_pool.Add(i, cNameAndType);
|
|
break;
|
|
|
|
case 15:
|
|
CONSTANT_MethodHandle_info cMethodHandle = new CONSTANT_MethodHandle_info(tag);
|
|
cMethodHandle.reference_kind = br.ReadByte();
|
|
cMethodHandle.reference_index = br.ReadInt16BE();
|
|
constant_pool.Add(i, cMethodHandle);
|
|
break;
|
|
|
|
case 16:
|
|
CONSTANT_MethodType_info cMethodType = new CONSTANT_MethodType_info(tag);
|
|
cMethodType.descriptor_index = br.ReadInt16BE();
|
|
constant_pool.Add(i, cMethodType);
|
|
break;
|
|
|
|
case 18:
|
|
CONSTANT_InvokeDynamic_info cInvokeDynamic = new CONSTANT_InvokeDynamic_info(tag);
|
|
cInvokeDynamic.bootstrap_method_attr_index = br.ReadInt16BE();
|
|
cInvokeDynamic.name_and_type_index = br.ReadInt16BE();
|
|
constant_pool.Add(i, cInvokeDynamic);
|
|
break;
|
|
|
|
default:
|
|
Console.WriteLine("(EE) ERREUR code inconnu : {0:X2}", tag);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void readInterfaces(BinaryReader br)
|
|
{
|
|
interfaces = new List<Int16>();
|
|
|
|
interfaces_count = br.ReadInt16BE();
|
|
|
|
for (int i = 0; i < interfaces_count; i++)
|
|
interfaces.Add(br.ReadInt16BE());
|
|
}
|
|
|
|
private void readFields(BinaryReader br)
|
|
{
|
|
fields = new Dictionary<int, stField>();
|
|
|
|
fields_count = br.ReadInt16BE();
|
|
|
|
for (int i = 0; i < fields_count; i++)
|
|
{
|
|
stField st = new stField();
|
|
|
|
st.access_flags = br.ReadInt16BE();
|
|
st.name_index = br.ReadInt16BE();
|
|
st.descriptor_index = br.ReadInt16BE();
|
|
st.attributes_count = br.ReadInt16BE();
|
|
|
|
if (st.attributes_count > 0)
|
|
{
|
|
st.attributes = new Dictionary<int, stAttribut>();
|
|
|
|
for (int j = 0; j < st.attributes_count; j++)
|
|
{
|
|
stAttribut stA = new stAttribut();
|
|
|
|
readAttributes(br, ref stA);
|
|
|
|
st.attributes.Add(j + 1, stA);
|
|
}
|
|
}
|
|
|
|
fields.Add(i + 1, st);
|
|
}
|
|
}
|
|
|
|
private void readMethods(BinaryReader br)
|
|
{
|
|
methods = new Dictionary<int, stMethod>();
|
|
|
|
methods_count = br.ReadInt16BE();
|
|
|
|
for (int i = 0; i < methods_count; i++)
|
|
{
|
|
stMethod st = new stMethod();
|
|
|
|
st.access_flags = br.ReadInt16BE();
|
|
st.name_index = br.ReadInt16BE();
|
|
st.descriptor_index = br.ReadInt16BE();
|
|
st.attributes_count = br.ReadInt16BE();
|
|
|
|
if (st.attributes_count > 0)
|
|
{
|
|
st.attributes = new Dictionary<int, stAttribut>();
|
|
|
|
for (int j = 0; j < st.attributes_count; j++)
|
|
{
|
|
stAttribut stA = new stAttribut();
|
|
|
|
readAttributes(br, ref stA);
|
|
|
|
st.attributes.Add(j + 1, stA);
|
|
}
|
|
}
|
|
|
|
methods.Add(i + 1, st);
|
|
}
|
|
|
|
}
|
|
|
|
private void readAttributes(BinaryReader br)
|
|
{
|
|
attributes = new Dictionary<int, stAttribut>();
|
|
|
|
attributes_count = br.ReadInt16BE();
|
|
|
|
for (int i = 0; i < attributes_count; i++)
|
|
{
|
|
stAttribut st = new stAttribut();
|
|
|
|
readAttributes(br, ref st);
|
|
|
|
attributes.Add(i + 1, st);
|
|
}
|
|
}
|
|
|
|
private void readAttributes(BinaryReader br, ref stAttribut st)
|
|
{
|
|
st.attribute_name_index = br.ReadInt16BE();
|
|
st.attribute_length = br.ReadInt32BE();
|
|
|
|
if (st.attribute_length > 0)
|
|
{
|
|
st.info = new byte[st.attribute_length];
|
|
st.info = br.ReadBytes((int)st.attribute_length);
|
|
}
|
|
}
|
|
|
|
private int readBytes(byte[] bytes, int nb, ref int num)
|
|
{
|
|
int value = 0;
|
|
|
|
for (int i = 0; i < nb; i++)
|
|
value = value * 0x100 + bytes[num++];
|
|
|
|
return value;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Print data
|
|
|
|
// NOT FINISH //
|
|
private void printBytecodeCode(StreamWriter sw, byte[] bytes)
|
|
{
|
|
List<stOpcode> list = new List<stOpcode>();
|
|
string[] s;
|
|
byte temp;
|
|
int num = 0;
|
|
stOpcode st;
|
|
|
|
sw.Write(string.Format("max_stack = {0:X4}\n", readBytes(bytes, 2, ref num)));
|
|
sw.Write(string.Format("{0,60} = {1:X4}\n", "max_locals", readBytes(bytes, 2, ref num)));
|
|
sw.Write(string.Format("{0,61} = {1:X8}\n", "code_length", readBytes(bytes, 4, ref num)));
|
|
|
|
|
|
while (num < bytes.Length - 8)
|
|
{
|
|
st = new stOpcode();
|
|
st.opcode = bytes[num++];
|
|
byte op = st.opcode;
|
|
|
|
sw.Write(string.Format("{0,52:X2} ", op));
|
|
|
|
if (op == 0x00)
|
|
//st.name = "NOP";
|
|
sw.Write("NOP\n");
|
|
else if (op == 0x01)
|
|
//st.name = "CONSTNULL";
|
|
sw.Write("CONSTNULL\n");
|
|
else if (op <= 11)
|
|
{
|
|
sw.Write("CONST (");
|
|
//st.name = "CONST";
|
|
if (op <= 0x08)
|
|
{
|
|
sw.Write(string.Format("I = {0}", op - 3));
|
|
//st.type = "I";
|
|
//st.value = op - 3;
|
|
}
|
|
else if (op <= 0x0A)
|
|
{
|
|
sw.Write(string.Format("L = {0}", op - 9));
|
|
//st.type = "L";
|
|
//st.value = op - 9;
|
|
}
|
|
else if (op <= 0x0D)
|
|
{
|
|
sw.Write(string.Format("F = {0}", op - 0x0B));
|
|
//st.type = "F";
|
|
//st.value = op - 0x0B;
|
|
}
|
|
else if (op <= 0x0F)
|
|
{
|
|
sw.Write(string.Format("D = {0}", op - 0x0E));
|
|
//st.type = "D";
|
|
//st.value = op - 0x0E;
|
|
}
|
|
else if (op == 0x10)
|
|
{
|
|
sw.Write(string.Format("I = {0}", bytes[num++]));
|
|
//st.type = "I";
|
|
//st.value = bytes[num++];
|
|
}
|
|
else
|
|
{
|
|
sw.Write(string.Format("I = {0}", readBytes(bytes, 2, ref num)));
|
|
//st.type = "I";
|
|
//st.value = bytes[num++] * 0x100 + bytes[num++];
|
|
}
|
|
sw.Write(")\n");
|
|
}
|
|
else if (op == 0x12)
|
|
{
|
|
sw.Write(string.Format("LDC ({0} = 1)\n", bytes[num++].ToString()));
|
|
//st.name = "LDC";
|
|
//st.type = bytes[num++].ToString();
|
|
//st.value = 1;
|
|
}
|
|
else if (op == 0x13)
|
|
{
|
|
sw.Write(string.Format("LDC ({0} = 1)\n", readBytes(bytes, 2, ref num).ToString()));
|
|
//st.name = "LDC";
|
|
//st.type = (bytes[num++] * 0x100 + bytes[num++]).ToString();
|
|
//st.value = 1;
|
|
}
|
|
else if (op == 0x14)
|
|
{
|
|
sw.Write(string.Format("LDC ({0} = 2)\n", readBytes(bytes, 2, ref num).ToString()));
|
|
//st.name = "LDC";
|
|
//st.type = (bytes[num++] * 0x100 + bytes[num++]).ToString();
|
|
//st.value = 2;
|
|
}
|
|
else if (op <= 0x2D)
|
|
{
|
|
s = new string[] { "I", "L", "F", "D", "A" };
|
|
sw.Write("LOAD (");
|
|
if (op <= 0x19)
|
|
{
|
|
temp = (byte)(op - 0x15);
|
|
//st.type = s[temp];
|
|
//st.value = bytes[num++];
|
|
sw.Write(string.Format("type={0} value={1}", s[temp], bytes[num++]));
|
|
}
|
|
else
|
|
{
|
|
temp = (byte)(op - 0x1A);
|
|
//st.type = s[temp/4];
|
|
//st.value = temp % 4;
|
|
sw.Write(string.Format("type={0} value={1}", s[temp / 4], temp % 4));
|
|
}
|
|
sw.Write(")\n");
|
|
s = null;
|
|
}
|
|
else if (op <= 0x35)
|
|
{
|
|
s = new string[] { "I", "L", "F", "D", "A", "B", "C", "S" };
|
|
if (s[op - 0x2E] != "A")
|
|
{
|
|
sw.Write(string.Format("ARRLOAD (type={0})\n", s[op - 0x2E]));
|
|
//st.type = s[op - 0x2E];
|
|
//st.name = "ARRLOAD";
|
|
}
|
|
else
|
|
sw.Write("ARRLOAD_OBJ\n");
|
|
//st.name = "ARRLOAD_OBJ";
|
|
s = null;
|
|
}
|
|
else if (op <= 0x4E)
|
|
{
|
|
s = new string[] { "I", "L", "F", "D", "A" };
|
|
//st.name = "STORE";
|
|
sw.Write("STORE");
|
|
if (op <= 0x3A)
|
|
{
|
|
sw.Write(string.Format(" (type={0} value={1})\n", s[op - 0x36], bytes[num++]));
|
|
//st.type = s[op - 0x36];
|
|
//st.value = bytes[num++];
|
|
}
|
|
else
|
|
{
|
|
temp = (byte)(op - 0x3B);
|
|
sw.Write(string.Format(" (type={0} value={1})\n", s[temp / 4], temp % 4));
|
|
//st.type = s[temp / 4];
|
|
//st.value = temp % 4;
|
|
}
|
|
s = null;
|
|
}
|
|
else if (op <= 0x56)
|
|
{
|
|
s = new string[] { "I", "L", "F", "D", "A", "B", "C", "S" };
|
|
if (s[op - 0x4F] != "A")
|
|
{
|
|
sw.Write(string.Format("ARRSTORE (type={0})\n", s[op - 0x4F]));
|
|
//st.type = s[op - 0x4F];
|
|
//st.name = "ARRSTORE";
|
|
}
|
|
else
|
|
sw.Write("ARRSTORE_OBJ\n");
|
|
//st.name = "ARRSTORE_OBJ";
|
|
s = null;
|
|
}
|
|
else if (op == 0x57)
|
|
sw.Write("POP\n");
|
|
// st.name = "POP";
|
|
else if (op == 0x58)
|
|
sw.Write("POP2\n");
|
|
// st.name = "POP2";
|
|
else if (op == 0x59)
|
|
sw.Write("DUP\n");
|
|
// st.name = "DUP";
|
|
else if (op == 0x5A)
|
|
sw.Write("DUPX1\n");
|
|
// st.name = "DUPX1";
|
|
else if (op == 0x5B)
|
|
sw.Write("DUPX2\n");
|
|
// st.name = "DUPX2";
|
|
else if (op == 0x5C)
|
|
sw.Write("DUP2\n");
|
|
// st.name = "DUP2";
|
|
else if (op == 0x5D)
|
|
sw.Write("DUP2X1\n");
|
|
// st.name = "DUP2X1";
|
|
else if (op == 0x5E)
|
|
sw.Write("DUP2X2\n");
|
|
// st.name = "DUP2X2";
|
|
else if (op == 0x5F)
|
|
sw.Write("SWAP\n");
|
|
// st.name = "SWAP";
|
|
else if (op <= 0x77)
|
|
{
|
|
s = new string[] { "I", "L", "F", "D" };
|
|
temp = (byte)(op - 0x60);
|
|
switch (temp / 4)
|
|
{
|
|
case 0:
|
|
sw.Write("ADD");
|
|
//st.name = "ADD";
|
|
break;
|
|
case 1:
|
|
sw.Write("SUB");
|
|
//st.name = "SUB";
|
|
break;
|
|
case 2:
|
|
sw.Write("MUL");
|
|
//st.name = "MUL";
|
|
break;
|
|
case 3:
|
|
sw.Write("DIV");
|
|
//st.name = "DIV";
|
|
break;
|
|
case 4:
|
|
sw.Write("REM");
|
|
//st.name = "REM";
|
|
break;
|
|
case 5:
|
|
sw.Write("NEG");
|
|
//st.name = "NEG";
|
|
break;
|
|
}
|
|
sw.Write(string.Format(" (type={0})\n", s[temp % 4]));
|
|
//st.type = s[temp % 4];
|
|
s = null;
|
|
}
|
|
else if (op <= 0x83)
|
|
{
|
|
temp = (byte)(op - 0x78);
|
|
switch (temp / 2)
|
|
{
|
|
case 0:
|
|
sw.Write("SHL");
|
|
//st.name = "SHL";
|
|
break;
|
|
case 1:
|
|
sw.Write("SHR");
|
|
//st.name = "SHR";
|
|
break;
|
|
case 2:
|
|
sw.Write("USHR");
|
|
//st.name = "USHR";
|
|
break;
|
|
case 3:
|
|
sw.Write("AND");
|
|
//st.name = "AND";
|
|
break;
|
|
case 4:
|
|
sw.Write("OR");
|
|
//st.name = "OR";
|
|
break;
|
|
case 5:
|
|
sw.Write("WOR");
|
|
//st.name = "WOR";
|
|
break;
|
|
}
|
|
if (temp % 2 == 0)
|
|
sw.Write(" (type=I)\n");
|
|
//st.type = "I";
|
|
else
|
|
sw.Write(" (type=L)\n");
|
|
//st.type = "L";
|
|
}
|
|
else if (op == 0x84)
|
|
{
|
|
sw.Write(string.Format("IINC (type={0} value={1})\n", bytes[num++].ToString(), bytes[num++]));
|
|
//st.name = "IINC";
|
|
//st.type = bytes[num++].ToString();
|
|
//st.value = bytes[num++];
|
|
}
|
|
else if (op <= 0x90)
|
|
{
|
|
s = new string[] { "I", "I", "I", "L", "L", "L", "F", "F", "F", "D", "D", "D" };
|
|
string[] s2 = new string[] { "L", "F", "D", "I", "F", "D", "I", "L", "D", "I", "L", "F" };
|
|
sw.Write(string.Format("CONVERT ({0} -> {1})\n", s[op - 0x85], s2[op - 0x85]));
|
|
//st.name = "CONVERT";
|
|
//st.src_t = s[op - 0x85];
|
|
//st.dst_t = s2[op - 0x85];
|
|
s = null;
|
|
s2 = null;
|
|
}
|
|
else if (op <= 0x93)
|
|
{
|
|
sw.Write("TRUNCATE");
|
|
//st.name = "TRUNCATE";
|
|
switch (op - 0x91)
|
|
{
|
|
case 0:
|
|
sw.Write(" (type=B)\n");
|
|
//st.type = "B";
|
|
break;
|
|
case 1:
|
|
sw.Write(" (type=C)\n");
|
|
//st.type = "C";
|
|
break;
|
|
case 2:
|
|
sw.Write(" (type=S)\n");
|
|
//st.type = "S";
|
|
break;
|
|
}
|
|
}
|
|
else if (op == 0x94)
|
|
sw.Write("LCMP\n");
|
|
//st.name = "LCMP";
|
|
else if (op <= 0x98)
|
|
{
|
|
sw.Write("FCMP");
|
|
//st.name = "FCMP";
|
|
temp = (byte)(op - 0x95);
|
|
if (temp / 2 == 0)
|
|
sw.Write(" (type=F");
|
|
//st.type = "F";
|
|
else
|
|
sw.Write(" (type=D");
|
|
//st.type = "D";
|
|
|
|
if (temp % 2 == 0)
|
|
sw.Write(" value=-1)\n");
|
|
//st.value = -1;
|
|
else
|
|
sw.Write(" value=1)\n");
|
|
//st.value = 1;
|
|
}
|
|
else if (op <= 0x9E)
|
|
{
|
|
st.name = "IF_I";
|
|
switch (op - 0x99)
|
|
{
|
|
case 0:
|
|
st.type = "eq";
|
|
break;
|
|
case 1:
|
|
st.type = "ne";
|
|
break;
|
|
case 2:
|
|
st.type = "lt";
|
|
break;
|
|
case 3:
|
|
st.type = "ge";
|
|
break;
|
|
case 4:
|
|
st.type = "gt";
|
|
break;
|
|
case 5:
|
|
st.type = "le";
|
|
break;
|
|
}
|
|
sw.Write(string.Format("IF_I (type={0} value={1})\n", st.type, readBytes(bytes, 2, ref num)));
|
|
//st.value = bytes[num++] * 0x100 + bytes[num++];
|
|
}
|
|
else if (op <= 0xA4)
|
|
{
|
|
st.name = "IF_ICMP";
|
|
switch (op - 0x9F)
|
|
{
|
|
case 0:
|
|
st.type = "eq";
|
|
break;
|
|
case 1:
|
|
st.type = "ne";
|
|
break;
|
|
case 2:
|
|
st.type = "lt";
|
|
break;
|
|
case 3:
|
|
st.type = "ge";
|
|
break;
|
|
case 4:
|
|
st.type = "gt";
|
|
break;
|
|
case 5:
|
|
st.type = "le";
|
|
break;
|
|
}
|
|
//st.value = bytes[num++] * 0x100 + bytes[num++];
|
|
sw.Write(string.Format("IF_ICMP (type={0} value={1})\n", st.type, readBytes(bytes, 2, ref num)));
|
|
}
|
|
else if (op <= 0xA6)
|
|
{
|
|
st.name = "IF_ACMP";
|
|
switch (op - 0xA5)
|
|
{
|
|
case 0:
|
|
st.type = "eq";
|
|
break;
|
|
case 1:
|
|
st.type = "ne";
|
|
break;
|
|
}
|
|
//st.value = bytes[num++] * 0x100 + bytes[num++];
|
|
sw.Write(string.Format("IF_ACMP (type={0} value={1})\n", st.type, readBytes(bytes, 2, ref num)));
|
|
}
|
|
else if (op == 0xA7)
|
|
{
|
|
st.name = "GOTO";
|
|
//st.value = bytes[num++] * 0x100 + bytes[num++];
|
|
sw.Write(string.Format("GOTO (value={0})\n", readBytes(bytes, 2, ref num)));
|
|
}
|
|
else if (op == 0xA8)
|
|
{
|
|
st.name = "JSR";
|
|
//st.value = bytes[num++] * 0x100 + bytes[num++];
|
|
sw.Write(string.Format("JSR (value={0})\n", readBytes(bytes, 2, ref num)));
|
|
}
|
|
else if (op == 0xA9)
|
|
{
|
|
st.name = "RET";
|
|
//st.value = bytes[num++];
|
|
sw.Write(string.Format("RET (value={0})\n", bytes[num++]));
|
|
}
|
|
else if (op == 0xAA)
|
|
{
|
|
st.name = "SWITCH";
|
|
sw.Write("SWITCH");
|
|
readBytes(bytes, (3 - num) % 4, ref num);
|
|
sw.Write(" (default={0}", readBytes(bytes, 4, ref num));
|
|
int low = readBytes(bytes, 4, ref num);
|
|
int high = readBytes(bytes, 4, ref num);
|
|
for (int i = 0; i < high - low + 1; i++)
|
|
sw.Write(string.Format(" offset={0}", readBytes(bytes, 4, ref num)));
|
|
sw.Write("\n");
|
|
//st.default = bytes[num++] * 0x1000000 + bytes[num++] * 0x10000 + bytes[num++] * 0x100 + bytes[num++];
|
|
//st.low = bytes[num++] * 0x1000000 + bytes[num++] * 0x10000 + bytes[num++] * 0x100 + bytes[num++];
|
|
//st.high = bytes[num++] * 0x1000000 + bytes[num++] * 0x10000 + bytes[num++] * 0x100 + bytes[num++];
|
|
//st.offset = bytes[num++] * 0x1000000 + bytes[num++] * 0x10000 + bytes[num++] * 0x100 + bytes[num++];
|
|
|
|
}
|
|
else if (op == 0xAB)
|
|
{
|
|
st.name = "SWITCH";
|
|
sw.Write("SWITCH");
|
|
readBytes(bytes, (3 - num) % 4, ref num);
|
|
sw.Write(" (default={0}", readBytes(bytes, 4, ref num));
|
|
int numpairs = readBytes(bytes, 4, ref num);
|
|
for (int i = 0; i < numpairs + 1; i++)
|
|
sw.Write(string.Format(" offset={0}", readBytes(bytes, 4, ref num)));
|
|
sw.Write("\n");
|
|
}
|
|
else if (op <= 0xB1)
|
|
{
|
|
st.name = "RETURN";
|
|
switch (op - 0xAC)
|
|
{
|
|
case 0:
|
|
st.type = "I";
|
|
break;
|
|
case 1:
|
|
st.type = "L";
|
|
break;
|
|
case 2:
|
|
st.type = "F";
|
|
break;
|
|
case 3:
|
|
st.type = "D";
|
|
break;
|
|
case 4:
|
|
st.type = "A";
|
|
break;
|
|
case 5:
|
|
st.type = "None";
|
|
break;
|
|
}
|
|
}
|
|
else if (op == 0xB2)
|
|
sw.Write("GETSTATIC\n");
|
|
//st.name = "GETSTATIC";
|
|
else if (op == 0xB3)
|
|
sw.Write("PUTSTATIC\n");
|
|
//st.name = "PUTSTATIC";
|
|
else if (op == 0xB4)
|
|
sw.Write("GETFIELD\n");
|
|
//st.name = "GETFIELD";
|
|
else if (op == 0xB5)
|
|
sw.Write("PUTFIELD\n");
|
|
//st.name = "PUTFIELD";
|
|
else if (op == 0xB6)
|
|
sw.Write("INVOKEVIRTUAL\n");
|
|
//st.name = "INVOKEVIRTUAL";
|
|
else if (op == 0xB7)
|
|
sw.Write("INVOKESPECIAL\n");
|
|
//st.name = "INVOKESPECIAL";
|
|
else if (op == 0xB8)
|
|
sw.Write("INVOKESTATIC\n");
|
|
//st.name = "INVOKESTATIC";
|
|
else if (op == 0xB9)
|
|
{
|
|
sw.Write(string.Format("INVOKEINTERFACE (index={0} count={1} zero={2})\n", readBytes(bytes, 2, ref num), bytes[num++], bytes[num++]));
|
|
//st.name = "INVOKEINTERFACE";
|
|
//st.index = bytes[num++] * 0x100 + bytes[num++];
|
|
//st.count = bytes[num++];
|
|
//st.zero = bytes[num++];
|
|
}
|
|
else if (op == 0xBA)
|
|
{
|
|
sw.Write(string.Format("INVOKEDYNAMIC (index={0} zero={1})\n", readBytes(bytes, 2, ref num), readBytes(bytes, 2, ref num)));
|
|
//st.name = "INVOKEDYNAMIC";
|
|
//st.index = bytes[num++] * 0x100 + bytes[num++];
|
|
//st.zero = bytes[num++] * 0x100 + bytes[num++];
|
|
}
|
|
else if (op == 0xBB)
|
|
sw.Write("NEW\n");
|
|
//st.name = "NEW";
|
|
else if (op == 0xBC)
|
|
{
|
|
sw.Write(string.Format("NEWARRAY"));
|
|
temp = bytes[num++];
|
|
//st.name = "NEWARRAY";
|
|
switch (temp)
|
|
{
|
|
case 4:
|
|
sw.Write(" (Bool)");
|
|
//st.type = "Bool";
|
|
break;
|
|
case 5:
|
|
sw.Write(" (C)");
|
|
//st.type = "C";
|
|
break;
|
|
case 6:
|
|
sw.Write(" (F)");
|
|
//st.type = "F";
|
|
break;
|
|
case 7:
|
|
sw.Write(" (D)");
|
|
//st.type = "D";
|
|
break;
|
|
case 8:
|
|
sw.Write(" (B)");
|
|
//st.type = "B";
|
|
break;
|
|
case 9:
|
|
sw.Write(" (S)");
|
|
//st.type = "S";
|
|
break;
|
|
case 10:
|
|
sw.Write(" (I)");
|
|
//st.type = "I";
|
|
break;
|
|
case 11:
|
|
sw.Write(" (L)");
|
|
//st.type = "L";
|
|
break;
|
|
}
|
|
sw.Write("\n");
|
|
}
|
|
else if (op == 0xBD)
|
|
sw.Write("ANEWARRAY\n");
|
|
//st.name = "ANEWARRAY";
|
|
else if (op == 0xBE)
|
|
sw.Write("ARRLEN\n");
|
|
//st.name = "ARRLEN";
|
|
else if (op == 0xBF)
|
|
sw.Write("THROW\n");
|
|
//st.name = "THROW";
|
|
else if (op == 0xC0)
|
|
sw.Write("CHECKCAST\n");
|
|
//st.name = "CHECKCAST";
|
|
else if (op == 0xC1)
|
|
sw.Write("INSTANCEOF\n");
|
|
//st.name = "INSTANCEOF";
|
|
else if (op == 0xC2)
|
|
sw.Write("MONENTER\n");
|
|
//st.name = "MONENTER";
|
|
else if (op == 0xC3)
|
|
sw.Write("MONEXIT\n");
|
|
//st.name = "MONEXIT";
|
|
else if (op == 0xC4)
|
|
{
|
|
byte b = bytes[num++];
|
|
if (b >= 0x15 && b < 0x1A)
|
|
{
|
|
sw.Write("LOAD (");
|
|
//st.name = "LOAD";
|
|
switch (b - 0x15)
|
|
{
|
|
case 0:
|
|
sw.Write("I = ");
|
|
//st.type = "I";
|
|
break;
|
|
case 1:
|
|
sw.Write("L = ");
|
|
//st.type = "L";
|
|
break;
|
|
case 2:
|
|
sw.Write("F = ");
|
|
//st.type = "F";
|
|
break;
|
|
case 3:
|
|
sw.Write("D = ");
|
|
//st.type = "D";
|
|
break;
|
|
case 4:
|
|
sw.Write("A = ");
|
|
//st.type = "A";
|
|
break;
|
|
}
|
|
//st.value = bytes[num++] * 0x100 + bytes[num++];
|
|
sw.Write(string.Format("{0})\n", readBytes(bytes, 2, ref num)));
|
|
}
|
|
else if (b >= 0x36 && b < 0x3B)
|
|
{
|
|
sw.Write("STORE (");
|
|
//st.name = "STORE";
|
|
switch (b - 0x36)
|
|
{
|
|
case 0:
|
|
sw.Write("I = ");
|
|
//st.type = "I";
|
|
break;
|
|
case 1:
|
|
sw.Write("L = ");
|
|
//st.type = "L";
|
|
break;
|
|
case 2:
|
|
sw.Write("F = ");
|
|
//st.type = "F";
|
|
break;
|
|
case 3:
|
|
sw.Write("D = ");
|
|
//st.type = "D";
|
|
break;
|
|
case 4:
|
|
sw.Write("A = ");
|
|
//st.type = "A";
|
|
break;
|
|
}
|
|
//st.value = bytes[num++] * 0x100 + bytes[num++];
|
|
sw.Write(string.Format("{0})\n", readBytes(bytes, 2, ref num)));
|
|
}
|
|
else if (b == 0xA9)
|
|
{
|
|
sw.Write(string.Format("RET ({0})\n", readBytes(bytes, 2, ref num)));
|
|
//st.name = "RET";
|
|
//st.value = bytes[num++] * 0x100 + bytes[num++];
|
|
}
|
|
else if (b == 0x84)
|
|
{
|
|
sw.Write(string.Format("IINC ({0} {1})\n", readBytes(bytes, 2, ref num), readBytes(bytes, 2, ref num)));
|
|
//st.name = "IINC";
|
|
//st.value = bytes[num++] * 0x100 + bytes[num++];
|
|
//st.value2 = bytes[num++] * 0x100 + bytes[num++];
|
|
}
|
|
}
|
|
else if (op == 0xC5)
|
|
{
|
|
sw.Write(string.Format("MULTINEWARRAY (index={0} dim={1})\n", readBytes(bytes, 2, ref num), bytes[num++]));
|
|
//st.name = "MULTINEWARRAY";
|
|
//st.index = bytes[num++] * 0x100 + bytes[num++];
|
|
//st.dim = bytes[num++];
|
|
}
|
|
else if (op <= 0xC7)
|
|
{
|
|
sw.Write("IF_A (");
|
|
//st.name = "IF_A";
|
|
if (op - 0xC6 == 0)
|
|
sw.Write(string.Format("eq -> {0})\n", readBytes(bytes, 2, ref num)));
|
|
//st.type = "eq";
|
|
else if (op - 0xC6 == 1)
|
|
sw.Write(string.Format("ne -> {0})\n", readBytes(bytes, 2, ref num)));
|
|
//st.type = "ne";
|
|
//st.jumptarget = bytes[num++] * 0x100 + bytes[num++];
|
|
}
|
|
else if (op == 0xC8)
|
|
{
|
|
sw.Write(string.Format("GOTO ({0})\n", readBytes(bytes, 4, ref num)));
|
|
//st.name = "GOTO";
|
|
//st.value = bytes[num++] * 0x1000000 + bytes[num++] * 0x10000 + bytes[num++] * 0x100 + bytes[num++];
|
|
}
|
|
else if (op == 0xC9)
|
|
{
|
|
sw.Write(string.Format("JSR ({0})\n", readBytes(bytes, 4, ref num)));
|
|
//st.name = "JSR";
|
|
//st.value = bytes[num++] * 0x1000000 + bytes[num++] * 0x10000 + bytes[num++] * 0x100 + bytes[num++];
|
|
}
|
|
else
|
|
Console.WriteLine("Bytecode inconnu : {0:X2}", op);
|
|
|
|
list.Add(st);
|
|
}
|
|
}
|
|
|
|
private void printBytecodeSourceFile(StreamWriter sw, byte[] bytes)
|
|
{
|
|
int num = 0;
|
|
|
|
sw.Write(string.Format("sourcefile_index = {0:X4}", readBytes(bytes, 2, ref num)));
|
|
}
|
|
|
|
private void printBytecodeInnerClass(StreamWriter sw, byte[] bytes)
|
|
{
|
|
int num = 0;
|
|
int nbClass = readBytes(bytes, 2, ref num);
|
|
|
|
sw.Write(string.Format("number_of_classes = {0:X4}\n", nbClass));
|
|
|
|
for (int i = 0; i < nbClass; i++)
|
|
{
|
|
sw.Write(string.Format("{0,34:D4} : inner_class_info_index = {1:X4}\n", i + 1, readBytes(bytes, 2, ref num)));
|
|
sw.Write(string.Format("{0,59} = {1:X4}\n", "outer_class_info_index", readBytes(bytes, 2, ref num)));
|
|
sw.Write(string.Format("{0,53} = {1:X4}\n", "inner_name_index", readBytes(bytes, 2, ref num)));
|
|
sw.Write(string.Format("{0,61} = {1:X4}\n", "inner_class_access_flags", readBytes(bytes, 2, ref num)));
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
private byte[] IntToByteArrayBE(int value, int size = 4)
|
|
{
|
|
byte[] bytes = BitConverter.GetBytes(value);
|
|
|
|
Array.Reverse(bytes, 0, size);
|
|
|
|
return bytes;
|
|
}
|
|
|
|
//---------------------------------------------------------------------
|
|
|
|
public void load(BinaryReader br)
|
|
{
|
|
magic = new byte[4];
|
|
magic = br.ReadBytes(4);
|
|
|
|
minor_version = br.ReadInt16BE();
|
|
major_version = br.ReadInt16BE();
|
|
|
|
readConstants(br);
|
|
|
|
access_flags = br.ReadInt16BE();
|
|
this_class = br.ReadInt16BE();
|
|
super_class = br.ReadInt16BE();
|
|
|
|
readInterfaces(br);
|
|
readFields(br);
|
|
readMethods(br);
|
|
readAttributes(br);
|
|
}
|
|
|
|
public Dictionary<int, string> getConstantsValue()
|
|
{
|
|
Dictionary<int, string> dict = new Dictionary<int, string>();
|
|
|
|
foreach (KeyValuePair<int, iCONSTANT> constant in constant_pool)
|
|
{
|
|
if (constant.Value.tag == 8)
|
|
{
|
|
CONSTANT_String_info stString = (CONSTANT_String_info)constant.Value;
|
|
|
|
dict[constant.Key] = getConstantValue(stString.string_index);
|
|
}
|
|
}
|
|
|
|
return dict;
|
|
}
|
|
|
|
public Dictionary<int, byte[]> getConstantsBytes()
|
|
{
|
|
Dictionary<int, byte[]> dict = new Dictionary<int, byte[]>();
|
|
|
|
foreach (KeyValuePair<int, iCONSTANT> constant in constant_pool)
|
|
{
|
|
if (constant.Value.tag == 8)
|
|
{
|
|
CONSTANT_String_info stString = (CONSTANT_String_info)constant.Value;
|
|
|
|
dict[constant.Key] = getConstantBytes(stString.string_index);
|
|
}
|
|
}
|
|
|
|
return dict;
|
|
}
|
|
|
|
public MemoryStream compilClass(evtClass.stFile originalFile)
|
|
{
|
|
MemoryStream ms = new MemoryStream();
|
|
|
|
using (BinaryWriter bw = new BinaryWriter(ms, Encoding.Default, true))
|
|
{
|
|
bw.Write(this.magic);
|
|
bw.Write(IntToByteArrayBE(this.minor_version, 2), 0, 2);
|
|
bw.Write(IntToByteArrayBE(this.major_version, 2), 0, 2);
|
|
|
|
bw.Write(IntToByteArrayBE(this.constant_pool_count+1, 2), 0, 2);
|
|
compilConstants(bw);
|
|
|
|
bw.Write(IntToByteArrayBE(this.access_flags, 2), 0, 2);
|
|
bw.Write(IntToByteArrayBE(this.this_class, 2), 0, 2);
|
|
bw.Write(IntToByteArrayBE(this.super_class, 2), 0, 2);
|
|
|
|
bw.Write(IntToByteArrayBE(this.interfaces_count, 2), 0, 2);
|
|
compilInterfaces(bw);
|
|
|
|
bw.Write(IntToByteArrayBE(this.fields_count, 2), 0, 2);
|
|
compilFields(bw);
|
|
|
|
bw.Write(IntToByteArrayBE(this.methods_count, 2), 0, 2);
|
|
compilMethods(bw);
|
|
|
|
bw.Write(IntToByteArrayBE(this.attributes_count, 2), 0, 2);
|
|
compilAttributes(bw);
|
|
}
|
|
|
|
return ms;
|
|
}
|
|
|
|
public void setConstantsBytes(int id, byte[] bytes)
|
|
{
|
|
if (constant_pool.ContainsKey(id))
|
|
{
|
|
if (constant_pool[id].tag == 8)
|
|
{
|
|
CONSTANT_String_info stString = (CONSTANT_String_info)constant_pool[id];
|
|
|
|
setConstantsBytes(stString.string_index, bytes);
|
|
}
|
|
else if (constant_pool[id].tag == 1)
|
|
{
|
|
CONSTANT_Utf8_info stUTF8 = (CONSTANT_Utf8_info)constant_pool[id];
|
|
|
|
stUTF8.bytes = new byte[bytes.Length];
|
|
Array.Copy(bytes, 0, stUTF8.bytes, 0, bytes.Length);
|
|
//stUTF8.bytes[bytes.Length] = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
public void writeConstants(StreamWriter sw)
|
|
{
|
|
sw.Write(string.Format("[CONSTANTS : {0}]\n", constant_pool_count));
|
|
|
|
foreach (KeyValuePair<int, iCONSTANT> constant in constant_pool)
|
|
{
|
|
sw.Write(string.Format("{0:X4} : {1:D2} ", constant.Key, constant.Value.tag));
|
|
|
|
switch (constant.Value.tag)
|
|
{
|
|
case 1:
|
|
CONSTANT_Utf8_info stUtf8 = (CONSTANT_Utf8_info)constant.Value;
|
|
|
|
sw.Write(string.Format("{0,-18} : {1:X4} ", "Utf8", stUtf8.length));
|
|
if (stUtf8.length > 0)
|
|
sw.Write(Encoding.UTF8.GetString(stUtf8.bytes).Replace("\n", "\\n"));
|
|
sw.Write("\n");
|
|
break;
|
|
|
|
case 3:
|
|
CONSTANT_Integer_info stInteger = (CONSTANT_Integer_info)constant.Value;
|
|
|
|
sw.Write(string.Format("{0,-18} : {1,-9:X8} ({1})\n", "Integer", stInteger.bytes));
|
|
break;
|
|
|
|
case 4:
|
|
CONSTANT_Float_info stFloat = (CONSTANT_Float_info)constant.Value;
|
|
|
|
sw.Write(string.Format("{0,-18} : {1,-9:X8} ({2})\n", "Float", stFloat.bytes, BitConverter.ToSingle(BitConverter.GetBytes(stFloat.bytes), 0)));
|
|
break;
|
|
|
|
case 5:
|
|
CONSTANT_Long_info stLong = (CONSTANT_Long_info)constant.Value;
|
|
|
|
sw.Write(string.Format("{0,-18} : {1:X8} {2:X8}\n", "Long", stLong.high_bytes, stLong.low_bytes));
|
|
break;
|
|
|
|
case 6:
|
|
CONSTANT_Double_info stDouble = (CONSTANT_Double_info)constant.Value;
|
|
|
|
sw.Write(string.Format("{0,-18} : {1:X8} {2:X8}\n", "Double", stDouble.high_bytes, stDouble.low_bytes));
|
|
break;
|
|
|
|
case 7:
|
|
CONSTANT_Class_info stClass = (CONSTANT_Class_info)constant.Value;
|
|
|
|
sw.Write(string.Format("{0,-18} : {1,-9:X4} ({2})\n", "Class", stClass.name_index, getConstantValue(stClass.name_index)));
|
|
break;
|
|
|
|
case 8:
|
|
CONSTANT_String_info stString = (CONSTANT_String_info)constant.Value;
|
|
|
|
sw.Write(string.Format("{0,-18} : {1,-9:X4} ({2})\n", "String", stString.string_index, getConstantValue(stString.string_index)));
|
|
break;
|
|
|
|
case 9:
|
|
CONSTANT_Fieldref_info stFieldref = (CONSTANT_Fieldref_info)constant.Value;
|
|
|
|
sw.Write(string.Format("{0,-18} : {1,-9:X4} ({2})\n", "Fieldref", stFieldref.class_index, getConstantValue(stFieldref.class_index)));
|
|
sw.Write(string.Format("{0,31}{1,-9:X4} ({2})\n", " ", stFieldref.name_and_type_index, getConstantValue(stFieldref.name_and_type_index)));
|
|
break;
|
|
|
|
case 10:
|
|
CONSTANT_Methodref_info stMethodref = (CONSTANT_Methodref_info)constant.Value;
|
|
|
|
sw.Write(string.Format("{0,-18} : {1,-9:X4} ({2})\n", "Methodref", stMethodref.class_index, getConstantValue(stMethodref.class_index)));
|
|
sw.Write(string.Format("{0,31}{1,-9:X4} ({2})\n", " ", stMethodref.name_and_type_index, getConstantValue(stMethodref.name_and_type_index)));
|
|
break;
|
|
|
|
case 11:
|
|
CONSTANT_InterfaceMethodref_info stInterfaceMethodref = (CONSTANT_InterfaceMethodref_info)constant.Value;
|
|
|
|
sw.Write(string.Format("{0,-18} : {1:X4} {2:X4}\n", "InterfaceMethodref", stInterfaceMethodref.class_index, stInterfaceMethodref.name_and_type_index));
|
|
break;
|
|
|
|
case 12:
|
|
CONSTANT_NameAndType_info stNameAndType = (CONSTANT_NameAndType_info)constant.Value;
|
|
|
|
sw.Write(string.Format("{0,-18} : {1,-9:X4} ({2})\n", "NameAndType", stNameAndType.name_index, getConstantValue(stNameAndType.name_index)));
|
|
sw.Write(string.Format("{0,31}{1,-9:X4} ({2})\n", " ", stNameAndType.descriptor_index, getConstantValue(stNameAndType.descriptor_index)));
|
|
break;
|
|
|
|
case 15:
|
|
CONSTANT_MethodHandle_info stMethodHandle = (CONSTANT_MethodHandle_info)constant.Value;
|
|
|
|
sw.Write(string.Format("{0,-18} : {1:X2} {2:X4}\n", "MethodHandle", stMethodHandle.reference_kind, stMethodHandle.reference_index));
|
|
break;
|
|
|
|
case 16:
|
|
CONSTANT_MethodType_info stMethodType = (CONSTANT_MethodType_info)constant.Value;
|
|
|
|
sw.Write(string.Format("{0,-18} : {1:X4}\n", "MethodType", stMethodType.descriptor_index));
|
|
break;
|
|
|
|
case 18:
|
|
CONSTANT_InvokeDynamic_info stInvokeDynamic = (CONSTANT_InvokeDynamic_info)constant.Value;
|
|
|
|
sw.Write(string.Format("{0,-18} : {1:X4} {2:X4}\n", "InvokeDynamic", stInvokeDynamic.bootstrap_method_attr_index, stInvokeDynamic.name_and_type_index));
|
|
break;
|
|
}
|
|
}
|
|
sw.Write("\n");
|
|
}
|
|
|
|
public void writeInterfaces(StreamWriter sw)
|
|
{
|
|
sw.Write(string.Format("[INTERFACES : {0}]\n", interfaces_count));
|
|
|
|
int num = 1;
|
|
foreach (Int16 index in interfaces)
|
|
{
|
|
sw.Write(string.Format("{0:D4} : {1:X4} ({2})\n", num, index, getConstantValue(index)));
|
|
num++;
|
|
}
|
|
sw.Write("\n");
|
|
}
|
|
|
|
public void writeFields(StreamWriter sw)
|
|
{
|
|
sw.Write(string.Format("[FIELDS : {0}]\n", fields_count));
|
|
|
|
foreach (KeyValuePair<int, stField> field in fields)
|
|
{
|
|
sw.Write(string.Format("{0:D4} : access_flags = {1:X4}\n", field.Key, field.Value.access_flags));
|
|
sw.Write(string.Format(" name_index = {0:X4} ({1})\n", field.Value.name_index, getConstantValue(field.Value.name_index)));
|
|
sw.Write(string.Format(" descriptor_index = {0:X4} ({1})\n", field.Value.descriptor_index, getConstantValue(field.Value.descriptor_index)));
|
|
sw.Write(string.Format(" attributes_count = {0:X4}\n", field.Value.attributes_count));
|
|
|
|
if (field.Value.attributes_count > 0)
|
|
{
|
|
foreach (KeyValuePair<int, stAttribut> attribut in field.Value.attributes)
|
|
{
|
|
sw.Write(string.Format(" attributes ({0:D4}) : attribute_name_index = {1:X4} ({2})\n", attribut.Key, attribut.Value.attribute_name_index, getConstantValue(attribut.Value.attribute_name_index)));
|
|
sw.Write(string.Format(" attribute_length = {0:X8}\n", attribut.Value.attribute_length));
|
|
|
|
sw.Write(" info = ");
|
|
for (int i = 0; i < attribut.Value.attribute_length; i++)
|
|
sw.Write(string.Format("{0:X2} ", attribut.Value.info[i]));
|
|
|
|
sw.Write("\n");
|
|
}
|
|
}
|
|
}
|
|
sw.Write("\n");
|
|
}
|
|
|
|
public void writeMethods(StreamWriter sw)
|
|
{
|
|
sw.Write(string.Format("[METHODS : {0}]\n", methods_count));
|
|
|
|
foreach (KeyValuePair<int, stMethod> method in methods)
|
|
{
|
|
sw.Write(string.Format("{0:D4} : access_flags = {1:X4}\n", method.Key, method.Value.access_flags));
|
|
sw.Write(string.Format(" name_index = {0:X4} ({1})\n", method.Value.name_index, getConstantValue(method.Value.name_index)));
|
|
sw.Write(string.Format(" descriptor_index = {0:X4} ({1})\n", method.Value.descriptor_index, getConstantValue(method.Value.descriptor_index)));
|
|
sw.Write(string.Format(" attributes_count = {0:X4}\n", method.Value.attributes_count));
|
|
|
|
if (method.Value.attributes_count > 0)
|
|
{
|
|
foreach (KeyValuePair<int, stAttribut> attribut in method.Value.attributes)
|
|
{
|
|
sw.Write(string.Format(" attributes ({0:D4}) : attribute_name_index = {1:X4} ({2})\n", attribut.Key, attribut.Value.attribute_name_index, getConstantValue(attribut.Value.attribute_name_index)));
|
|
sw.Write(string.Format(" attribute_length = {0:X8}\n", attribut.Value.attribute_length));
|
|
|
|
if (attribut.Value.attribute_length > 0)
|
|
{
|
|
sw.Write(string.Format("{0,31} = ", "info"));
|
|
switch (attribut.Value.attribute_name_index)
|
|
{
|
|
case 0x121:
|
|
printBytecodeCode(sw, attribut.Value.info);
|
|
break;
|
|
case 0x12A:
|
|
printBytecodeInnerClass(sw, attribut.Value.info);
|
|
break;
|
|
case 0x145:
|
|
printBytecodeSourceFile(sw, attribut.Value.info);
|
|
break;
|
|
}
|
|
//for (int i = 0; i < attribut.Value.attribute_length; i++)
|
|
// sw.Write(string.Format("{0:X2} ", attribut.Value.info[i]));
|
|
|
|
sw.Write("\n");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
sw.Write("\n");
|
|
}
|
|
|
|
public void writeAttributes(StreamWriter sw)
|
|
{
|
|
sw.Write(string.Format("[ATTRIBUTS : {0}]\n", attributes_count));
|
|
|
|
foreach (KeyValuePair<int, stAttribut> attribut in attributes)
|
|
{
|
|
sw.Write(string.Format("{0:D4} : attribute_name_index = {1:X4} ({2})\n", attribut.Key, attribut.Value.attribute_name_index, getConstantValue(attribut.Value.attribute_name_index)));
|
|
sw.Write(string.Format(" attribute_length = {0:X8}\n", attribut.Value.attribute_length));
|
|
|
|
if (attribut.Value.attribute_length > 0)
|
|
{
|
|
sw.Write(" info = ");
|
|
switch (attribut.Value.attribute_name_index)
|
|
{
|
|
case 0x121:
|
|
printBytecodeCode(sw, attribut.Value.info);
|
|
break;
|
|
case 0x12A:
|
|
printBytecodeInnerClass(sw, attribut.Value.info);
|
|
break;
|
|
case 0x145:
|
|
printBytecodeSourceFile(sw, attribut.Value.info);
|
|
break;
|
|
}
|
|
//for (int i = 0; i < attribut.Value.attribute_length; i++)
|
|
// sw.Write(string.Format("{0:X2} ", attribut.Value.info[i]));
|
|
|
|
sw.Write("\n");
|
|
}
|
|
}
|
|
sw.Write("\n");
|
|
}
|
|
}
|
|
}
|