mirror of
https://github.com/danbulant/Cosmos
synced 2026-05-20 04:48:53 +00:00
302 lines
No EOL
8.1 KiB
C#
302 lines
No EOL
8.1 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using System.IO;
|
|
|
|
namespace Indy.IL2CPU.IL {
|
|
public partial class ILReader {
|
|
private readonly MethodBody mBody;
|
|
private MemoryStream mStream;
|
|
private MethodBase mMethod;
|
|
private Module mModule;
|
|
public ILReader(MethodBase aMethod) {
|
|
mBody = aMethod.GetMethodBody();
|
|
mMethod = aMethod;
|
|
mModule = mMethod.Module;
|
|
mStream = new MemoryStream(mBody.GetILAsByteArray());
|
|
}
|
|
|
|
private OpCodeEnum mOpCode;
|
|
private byte[] mOperand;
|
|
private bool mHasOperand;
|
|
|
|
public int Position {
|
|
get;
|
|
private set;
|
|
}
|
|
|
|
public int NextPosition {
|
|
get {
|
|
return (int)mStream.Position;
|
|
}
|
|
}
|
|
|
|
public bool EndOfStream {
|
|
get {
|
|
return mStream.Position == mStream.Length;
|
|
}
|
|
}
|
|
|
|
public bool HasOperand {
|
|
get {
|
|
return mHasOperand;
|
|
}
|
|
}
|
|
|
|
public OpCodeEnum OpCode {
|
|
get {
|
|
return mOpCode;
|
|
}
|
|
}
|
|
|
|
public byte[] Operand {
|
|
get {
|
|
return mOperand;
|
|
}
|
|
}
|
|
|
|
private string mOperandValueStr;
|
|
public string OperandValueStr {
|
|
get {
|
|
if (mOperandValueStr == null) {
|
|
mOperandValueStr = mModule.ResolveString(OperandValueInt32);
|
|
}
|
|
return mOperandValueStr;
|
|
}
|
|
}
|
|
|
|
private MethodBase mOperandValueMethod;
|
|
public MethodBase OperandValueMethod {
|
|
get {
|
|
if (mOperandValueMethod == null) {
|
|
Type[] xTypeGenArgs = null;
|
|
Type[] xMethodGenArgs = null;
|
|
if (mMethod.DeclaringType.IsGenericType) {
|
|
xTypeGenArgs = mMethod.DeclaringType.GetGenericArguments();
|
|
}
|
|
if (mMethod.IsGenericMethod) {
|
|
xMethodGenArgs = mMethod.GetGenericArguments();
|
|
}
|
|
mOperandValueMethod = mModule.ResolveMethod(OperandValueInt32, xTypeGenArgs, xMethodGenArgs);
|
|
}
|
|
return mOperandValueMethod;
|
|
}
|
|
}
|
|
|
|
private uint? mOperandValueBranchPosition;
|
|
private bool mIsShortcut;
|
|
public uint OperandValueBranchPosition {
|
|
get {
|
|
if (mOperandValueBranchPosition == null) {
|
|
//sbyte xTemp = (sbyte)mOperand;
|
|
//if (xTemp == mOperand) {
|
|
// mOperandValueBranchPosition = NextPosition + xTemp;
|
|
//} else {
|
|
// if (mStream.Length < (NextPosition + mOperand + 1)) {
|
|
// mOperandValueBranchPosition = (uint)mOperand;
|
|
// } else {
|
|
// mOperandValueBranchPosition = (uint)(NextPosition + mOperand);
|
|
// }
|
|
if (!mIsShortcut) {
|
|
mOperandValueBranchPosition = (uint?)(NextPosition + OperandValueInt32);
|
|
} else {
|
|
mOperandValueBranchPosition = (uint?)(NextPosition + (sbyte)OperandValueInt32);
|
|
}
|
|
//}
|
|
}
|
|
return mOperandValueBranchPosition.Value;
|
|
}
|
|
}
|
|
|
|
private FieldInfo mOperandValueField;
|
|
public FieldInfo OperandValueField {
|
|
get {
|
|
if (mOperandValueField == null) {
|
|
Type[] xTypeGenArgs = null;
|
|
Type[] xMethodGenArgs = null;
|
|
if (mMethod.DeclaringType.IsGenericType) {
|
|
xTypeGenArgs = mMethod.DeclaringType.GetGenericArguments();
|
|
}
|
|
if (mMethod.IsGenericMethod) {
|
|
xMethodGenArgs = mMethod.GetGenericArguments();
|
|
}
|
|
mOperandValueField = mModule.ResolveField(OperandValueInt32, xTypeGenArgs, xMethodGenArgs);
|
|
}
|
|
return mOperandValueField;
|
|
}
|
|
}
|
|
|
|
private Type mOperandValueType;
|
|
public Type OperandValueType {
|
|
get {
|
|
if (mOperandValueType == null) {
|
|
Type[] xTypeGenArgs = null;
|
|
Type[] xMethodGenArgs = null;
|
|
if (mMethod.DeclaringType.IsGenericType) {
|
|
xTypeGenArgs = mMethod.DeclaringType.GetGenericArguments();
|
|
}
|
|
if (mMethod.IsGenericMethod) {
|
|
xMethodGenArgs = mMethod.GetGenericArguments();
|
|
}
|
|
mOperandValueType = mModule.ResolveType(OperandValueInt32, xTypeGenArgs, xMethodGenArgs);
|
|
}
|
|
return mOperandValueType;
|
|
}
|
|
}
|
|
|
|
public uint[] OperandValueBranchLocations {
|
|
get;
|
|
private set;
|
|
}
|
|
|
|
private int? mOperandValueInt32;
|
|
public int OperandValueInt32 {
|
|
get
|
|
{
|
|
if (!mIsShortcut)
|
|
{
|
|
if (mOperandValueInt32 == null)
|
|
{
|
|
byte[] xData = new byte[4];
|
|
Array.Copy(Operand, xData, Math.Min(4, Operand.Length));
|
|
mOperandValueInt32 = BitConverter.ToInt32(xData, 0);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
sbyte xShortValue = (sbyte)Operand[0];
|
|
mOperandValueInt32 = xShortValue;
|
|
}
|
|
return mOperandValueInt32.Value;
|
|
}
|
|
}
|
|
|
|
private Single? mOperandValueSingle;
|
|
public Single OperandValueSingle {
|
|
get {
|
|
if (mOperandValueSingle == null) {
|
|
mOperandValueSingle = BitConverter.ToSingle(Operand, 0);
|
|
}
|
|
return mOperandValueSingle.Value;
|
|
}
|
|
}
|
|
|
|
private Double? mOperandValueDouble;
|
|
public Double OperandValueDouble {
|
|
get {
|
|
if (mOperandValueDouble == null) {
|
|
mOperandValueDouble = BitConverter.ToDouble(Operand, 0);
|
|
}
|
|
return mOperandValueDouble.Value;
|
|
}
|
|
}
|
|
|
|
public bool Read() {
|
|
Position = NextPosition;
|
|
int xByteValueInt = mStream.ReadByte();
|
|
OpCodeEnum xOpCode;
|
|
if (xByteValueInt == -1) {
|
|
return false;
|
|
}
|
|
byte xByteValue = (byte)xByteValueInt;
|
|
if (xByteValue == 0xFE) {
|
|
xByteValueInt = mStream.ReadByte();
|
|
if (xByteValueInt == -1) {
|
|
return false;
|
|
}
|
|
xOpCode = (OpCodeEnum)(xByteValue << 8 | xByteValueInt);
|
|
} else {
|
|
xOpCode = (OpCodeEnum)xByteValue;
|
|
}
|
|
byte xOperandSize = GetOperandSize(xOpCode);
|
|
mOperand = null;
|
|
mOperandValueStr = null;
|
|
mOperandValueMethod = null;
|
|
mOperandValueField = null;
|
|
mOperandValueSingle = null;
|
|
mOperandValueType = null;
|
|
mOperandValueInt32 = null;
|
|
mOperandValueBranchPosition = null;
|
|
OperandValueBranchLocations = null;
|
|
mOperandValueDouble = null;
|
|
mOpCode = GetNonShortcutOpCode(xOpCode);
|
|
mIsShortcut = mOpCode != xOpCode;
|
|
mHasOperand = xOperandSize > 0;
|
|
if (mHasOperand) {
|
|
mOperand = ReadOperand(xOperandSize);
|
|
mOperandValueInt32 = GetInt32FromOperandByteArray(mOperand);
|
|
} else {
|
|
if (mOpCode != xOpCode) {
|
|
long? xTempOperand = GetShortcutOperand(xOpCode);
|
|
if (xTempOperand != null) {
|
|
mHasOperand = true;
|
|
mOperand = BitConverter.GetBytes(xTempOperand.Value);
|
|
}
|
|
}
|
|
if (mOpCode == OpCodeEnum.Switch) {
|
|
int[] xBranchLocations1 = new int[ReadInt32()];
|
|
for (int i = 0; i < xBranchLocations1.Length; i++) {
|
|
xBranchLocations1[i] = ReadInt32();
|
|
}
|
|
uint[] xResult = new uint[xBranchLocations1.Length];
|
|
for (int i = 0; i < xBranchLocations1.Length; i++) {
|
|
if ((NextPosition + xBranchLocations1[i]) < 0) {
|
|
xResult[i] = (uint)xBranchLocations1[i];
|
|
} else {
|
|
xResult[i] = (uint)(NextPosition + xBranchLocations1[i]);
|
|
}
|
|
}
|
|
OperandValueBranchLocations = xResult;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
private Int64 ReadInt64() {
|
|
long xResult = 0;
|
|
byte xOperandSize = 64;
|
|
byte[] xBytes = new byte[xOperandSize / 8];
|
|
while (xOperandSize > 0) {
|
|
int xByteValueInt = mStream.ReadByte();
|
|
if (xByteValueInt == -1) {
|
|
break;
|
|
}
|
|
xBytes[(xOperandSize / 8) - 1] = (byte)xByteValueInt;
|
|
xOperandSize -= 8;
|
|
}
|
|
for (int i = 0; i < xBytes.Length; i++) {
|
|
xResult = xResult << 8 | xBytes[i];
|
|
}
|
|
return xResult;
|
|
}
|
|
|
|
private byte[] ReadOperand(byte aOperandSize) {
|
|
byte[] xBytes = new byte[aOperandSize / 8];
|
|
int index = 0;
|
|
while (aOperandSize > 0) {
|
|
int xByteValueInt = mStream.ReadByte();
|
|
if (xByteValueInt == -1) {
|
|
break;
|
|
}
|
|
xBytes[index] = (byte)xByteValueInt;
|
|
index += 1;
|
|
aOperandSize -= 8;
|
|
}
|
|
return xBytes;
|
|
}
|
|
|
|
private static Int32 GetInt32FromOperandByteArray(byte[] aData) {
|
|
Int32 xResult = 0;
|
|
for (int i = aData.Length - 1; i >= 0; i--) {
|
|
xResult = xResult << 8 | aData[i];
|
|
}
|
|
return xResult;
|
|
}
|
|
|
|
private Int32 ReadInt32() {
|
|
return GetInt32FromOperandByteArray(ReadOperand(32));
|
|
}
|
|
}
|
|
} |