hybridclr_unity/Editor/3rds/UnityHook/LDasm.cs

910 lines
29 KiB
C#
Raw Normal View History

using System;
namespace DotNetDetour
{
/// <summary>
/// 用于计算汇编指令长度使用的是BlackBone的LDasm.c中的算法我把他翻译成C#了
/// </summary>
public unsafe class LDasm
{
const int F_INVALID = 0x01;
const int F_PREFIX = 0x02;
const int F_REX = 0x04;
const int F_MODRM = 0x08;
const int F_SIB = 0x10;
const int F_DISP = 0x20;
const int F_IMM = 0x40;
const int F_RELATIVE = 0x80;
const int OP_NONE = 0x00;
const int OP_INVALID = 0x80;
const int OP_DATA_I8 = 0x01;
const int OP_DATA_I16 = 0x02;
const int OP_DATA_I16_I32 = 0x04;
const int OP_DATA_I16_I32_I64 = 0x08;
const int OP_EXTENDED = 0x10;
const int OP_RELATIVE = 0x20;
const int OP_MODRM = 0x40;
const int OP_PREFIX = 0x80;
struct ldasm_data
{
public byte flags;
public byte rex;
public byte modrm;
public byte sib;
public byte opcd_offset;
public byte opcd_size;
public byte disp_offset;
public byte disp_size;
public byte imm_offset;
public byte imm_size;
}
static byte[] flags_table =
{
/* 00 */ OP_MODRM,
/* 01 */ OP_MODRM,
/* 02 */ OP_MODRM,
/* 03 */ OP_MODRM,
/* 04 */ OP_DATA_I8,
/* 05 */ OP_DATA_I16_I32,
/* 06 */ OP_NONE,
/* 07 */ OP_NONE,
/* 08 */ OP_MODRM,
/* 09 */ OP_MODRM,
/* 0A */ OP_MODRM,
/* 0B */ OP_MODRM,
/* 0C */ OP_DATA_I8,
/* 0D */ OP_DATA_I16_I32,
/* 0E */ OP_NONE,
/* 0F */ OP_NONE,
/* 10 */ OP_MODRM,
/* 11 */ OP_MODRM,
/* 12 */ OP_MODRM,
/* 13 */ OP_MODRM,
/* 14 */ OP_DATA_I8,
/* 15 */ OP_DATA_I16_I32,
/* 16 */ OP_NONE,
/* 17 */ OP_NONE,
/* 18 */ OP_MODRM,
/* 19 */ OP_MODRM,
/* 1A */ OP_MODRM,
/* 1B */ OP_MODRM,
/* 1C */ OP_DATA_I8,
/* 1D */ OP_DATA_I16_I32,
/* 1E */ OP_NONE,
/* 1F */ OP_NONE,
/* 20 */ OP_MODRM,
/* 21 */ OP_MODRM,
/* 22 */ OP_MODRM,
/* 23 */ OP_MODRM,
/* 24 */ OP_DATA_I8,
/* 25 */ OP_DATA_I16_I32,
/* 26 */ OP_PREFIX,
/* 27 */ OP_NONE,
/* 28 */ OP_MODRM,
/* 29 */ OP_MODRM,
/* 2A */ OP_MODRM,
/* 2B */ OP_MODRM,
/* 2C */ OP_DATA_I8,
/* 2D */ OP_DATA_I16_I32,
/* 2E */ OP_PREFIX,
/* 2F */ OP_NONE,
/* 30 */ OP_MODRM,
/* 31 */ OP_MODRM,
/* 32 */ OP_MODRM,
/* 33 */ OP_MODRM,
/* 34 */ OP_DATA_I8,
/* 35 */ OP_DATA_I16_I32,
/* 36 */ OP_PREFIX,
/* 37 */ OP_NONE,
/* 38 */ OP_MODRM,
/* 39 */ OP_MODRM,
/* 3A */ OP_MODRM,
/* 3B */ OP_MODRM,
/* 3C */ OP_DATA_I8,
/* 3D */ OP_DATA_I16_I32,
/* 3E */ OP_PREFIX,
/* 3F */ OP_NONE,
/* 40 */ OP_NONE,
/* 41 */ OP_NONE,
/* 42 */ OP_NONE,
/* 43 */ OP_NONE,
/* 44 */ OP_NONE,
/* 45 */ OP_NONE,
/* 46 */ OP_NONE,
/* 47 */ OP_NONE,
/* 48 */ OP_NONE,
/* 49 */ OP_NONE,
/* 4A */ OP_NONE,
/* 4B */ OP_NONE,
/* 4C */ OP_NONE,
/* 4D */ OP_NONE,
/* 4E */ OP_NONE,
/* 4F */ OP_NONE,
/* 50 */ OP_NONE,
/* 51 */ OP_NONE,
/* 52 */ OP_NONE,
/* 53 */ OP_NONE,
/* 54 */ OP_NONE,
/* 55 */ OP_NONE,
/* 56 */ OP_NONE,
/* 57 */ OP_NONE,
/* 58 */ OP_NONE,
/* 59 */ OP_NONE,
/* 5A */ OP_NONE,
/* 5B */ OP_NONE,
/* 5C */ OP_NONE,
/* 5D */ OP_NONE,
/* 5E */ OP_NONE,
/* 5F */ OP_NONE,
/* 60 */ OP_NONE,
/* 61 */ OP_NONE,
/* 62 */ OP_MODRM,
/* 63 */ OP_MODRM,
/* 64 */ OP_PREFIX,
/* 65 */ OP_PREFIX,
/* 66 */ OP_PREFIX,
/* 67 */ OP_PREFIX,
/* 68 */ OP_DATA_I16_I32,
/* 69 */ OP_MODRM | OP_DATA_I16_I32,
/* 6A */ OP_DATA_I8,
/* 6B */ OP_MODRM | OP_DATA_I8,
/* 6C */ OP_NONE,
/* 6D */ OP_NONE,
/* 6E */ OP_NONE,
/* 6F */ OP_NONE,
/* 70 */ OP_RELATIVE | OP_DATA_I8,
/* 71 */ OP_RELATIVE | OP_DATA_I8,
/* 72 */ OP_RELATIVE | OP_DATA_I8,
/* 73 */ OP_RELATIVE | OP_DATA_I8,
/* 74 */ OP_RELATIVE | OP_DATA_I8,
/* 75 */ OP_RELATIVE | OP_DATA_I8,
/* 76 */ OP_RELATIVE | OP_DATA_I8,
/* 77 */ OP_RELATIVE | OP_DATA_I8,
/* 78 */ OP_RELATIVE | OP_DATA_I8,
/* 79 */ OP_RELATIVE | OP_DATA_I8,
/* 7A */ OP_RELATIVE | OP_DATA_I8,
/* 7B */ OP_RELATIVE | OP_DATA_I8,
/* 7C */ OP_RELATIVE | OP_DATA_I8,
/* 7D */ OP_RELATIVE | OP_DATA_I8,
/* 7E */ OP_RELATIVE | OP_DATA_I8,
/* 7F */ OP_RELATIVE | OP_DATA_I8,
/* 80 */ OP_MODRM | OP_DATA_I8,
/* 81 */ OP_MODRM | OP_DATA_I16_I32,
/* 82 */ OP_MODRM | OP_DATA_I8,
/* 83 */ OP_MODRM | OP_DATA_I8,
/* 84 */ OP_MODRM,
/* 85 */ OP_MODRM,
/* 86 */ OP_MODRM,
/* 87 */ OP_MODRM,
/* 88 */ OP_MODRM,
/* 89 */ OP_MODRM,
/* 8A */ OP_MODRM,
/* 8B */ OP_MODRM,
/* 8C */ OP_MODRM,
/* 8D */ OP_MODRM,
/* 8E */ OP_MODRM,
/* 8F */ OP_MODRM,
/* 90 */ OP_NONE,
/* 91 */ OP_NONE,
/* 92 */ OP_NONE,
/* 93 */ OP_NONE,
/* 94 */ OP_NONE,
/* 95 */ OP_NONE,
/* 96 */ OP_NONE,
/* 97 */ OP_NONE,
/* 98 */ OP_NONE,
/* 99 */ OP_NONE,
/* 9A */ OP_DATA_I16 | OP_DATA_I16_I32,
/* 9B */ OP_NONE,
/* 9C */ OP_NONE,
/* 9D */ OP_NONE,
/* 9E */ OP_NONE,
/* 9F */ OP_NONE,
/* A0 */ OP_DATA_I8,
/* A1 */ OP_DATA_I16_I32_I64,
/* A2 */ OP_DATA_I8,
/* A3 */ OP_DATA_I16_I32_I64,
/* A4 */ OP_NONE,
/* A5 */ OP_NONE,
/* A6 */ OP_NONE,
/* A7 */ OP_NONE,
/* A8 */ OP_DATA_I8,
/* A9 */ OP_DATA_I16_I32,
/* AA */ OP_NONE,
/* AB */ OP_NONE,
/* AC */ OP_NONE,
/* AD */ OP_NONE,
/* AE */ OP_NONE,
/* AF */ OP_NONE,
/* B0 */ OP_DATA_I8,
/* B1 */ OP_DATA_I8,
/* B2 */ OP_DATA_I8,
/* B3 */ OP_DATA_I8,
/* B4 */ OP_DATA_I8,
/* B5 */ OP_DATA_I8,
/* B6 */ OP_DATA_I8,
/* B7 */ OP_DATA_I8,
/* B8 */ OP_DATA_I16_I32_I64,
/* B9 */ OP_DATA_I16_I32_I64,
/* BA */ OP_DATA_I16_I32_I64,
/* BB */ OP_DATA_I16_I32_I64,
/* BC */ OP_DATA_I16_I32_I64,
/* BD */ OP_DATA_I16_I32_I64,
/* BE */ OP_DATA_I16_I32_I64,
/* BF */ OP_DATA_I16_I32_I64,
/* C0 */ OP_MODRM | OP_DATA_I8,
/* C1 */ OP_MODRM | OP_DATA_I8,
/* C2 */ OP_DATA_I16,
/* C3 */ OP_NONE,
/* C4 */ OP_MODRM,
/* C5 */ OP_MODRM,
/* C6 */ OP_MODRM | OP_DATA_I8,
/* C7 */ OP_MODRM | OP_DATA_I16_I32,
/* C8 */ OP_DATA_I8 | OP_DATA_I16,
/* C9 */ OP_NONE,
/* CA */ OP_DATA_I16,
/* CB */ OP_NONE,
/* CC */ OP_NONE,
/* CD */ OP_DATA_I8,
/* CE */ OP_NONE,
/* CF */ OP_NONE,
/* D0 */ OP_MODRM,
/* D1 */ OP_MODRM,
/* D2 */ OP_MODRM,
/* D3 */ OP_MODRM,
/* D4 */ OP_DATA_I8,
/* D5 */ OP_DATA_I8,
/* D6 */ OP_NONE,
/* D7 */ OP_NONE,
/* D8 */ OP_MODRM,
/* D9 */ OP_MODRM,
/* DA */ OP_MODRM,
/* DB */ OP_MODRM,
/* DC */ OP_MODRM,
/* DD */ OP_MODRM,
/* DE */ OP_MODRM,
/* DF */ OP_MODRM,
/* E0 */ OP_RELATIVE | OP_DATA_I8,
/* E1 */ OP_RELATIVE | OP_DATA_I8,
/* E2 */ OP_RELATIVE | OP_DATA_I8,
/* E3 */ OP_RELATIVE | OP_DATA_I8,
/* E4 */ OP_DATA_I8,
/* E5 */ OP_DATA_I8,
/* E6 */ OP_DATA_I8,
/* E7 */ OP_DATA_I8,
/* E8 */ OP_RELATIVE | OP_DATA_I16_I32,
/* E9 */ OP_RELATIVE | OP_DATA_I16_I32,
/* EA */ OP_DATA_I16 | OP_DATA_I16_I32,
/* EB */ OP_RELATIVE | OP_DATA_I8,
/* EC */ OP_NONE,
/* ED */ OP_NONE,
/* EE */ OP_NONE,
/* EF */ OP_NONE,
/* F0 */ OP_PREFIX,
/* F1 */ OP_NONE,
/* F2 */ OP_PREFIX,
/* F3 */ OP_PREFIX,
/* F4 */ OP_NONE,
/* F5 */ OP_NONE,
/* F6 */ OP_MODRM,
/* F7 */ OP_MODRM,
/* F8 */ OP_NONE,
/* F9 */ OP_NONE,
/* FA */ OP_NONE,
/* FB */ OP_NONE,
/* FC */ OP_NONE,
/* FD */ OP_NONE,
/* FE */ OP_MODRM,
/* FF */ OP_MODRM
};
static byte[] flags_table_ex =
{
/* 0F00 */ OP_MODRM,
/* 0F01 */ OP_MODRM,
/* 0F02 */ OP_MODRM,
/* 0F03 */ OP_MODRM,
/* 0F04 */ OP_INVALID,
/* 0F05 */ OP_NONE,
/* 0F06 */ OP_NONE,
/* 0F07 */ OP_NONE,
/* 0F08 */ OP_NONE,
/* 0F09 */ OP_NONE,
/* 0F0A */ OP_INVALID,
/* 0F0B */ OP_NONE,
/* 0F0C */ OP_INVALID,
/* 0F0D */ OP_MODRM,
/* 0F0E */ OP_INVALID,
/* 0F0F */ OP_MODRM | OP_DATA_I8, //3Dnow
/* 0F10 */ OP_MODRM,
/* 0F11 */ OP_MODRM,
/* 0F12 */ OP_MODRM,
/* 0F13 */ OP_MODRM,
/* 0F14 */ OP_MODRM,
/* 0F15 */ OP_MODRM,
/* 0F16 */ OP_MODRM,
/* 0F17 */ OP_MODRM,
/* 0F18 */ OP_MODRM,
/* 0F19 */ OP_INVALID,
/* 0F1A */ OP_INVALID,
/* 0F1B */ OP_INVALID,
/* 0F1C */ OP_INVALID,
/* 0F1D */ OP_INVALID,
/* 0F1E */ OP_INVALID,
/* 0F1F */ OP_NONE,
/* 0F20 */ OP_MODRM,
/* 0F21 */ OP_MODRM,
/* 0F22 */ OP_MODRM,
/* 0F23 */ OP_MODRM,
/* 0F24 */ OP_MODRM | OP_EXTENDED, //SSE5
/* 0F25 */ OP_INVALID,
/* 0F26 */ OP_MODRM,
/* 0F27 */ OP_INVALID,
/* 0F28 */ OP_MODRM,
/* 0F29 */ OP_MODRM,
/* 0F2A */ OP_MODRM,
/* 0F2B */ OP_MODRM,
/* 0F2C */ OP_MODRM,
/* 0F2D */ OP_MODRM,
/* 0F2E */ OP_MODRM,
/* 0F2F */ OP_MODRM,
/* 0F30 */ OP_NONE,
/* 0F31 */ OP_NONE,
/* 0F32 */ OP_NONE,
/* 0F33 */ OP_NONE,
/* 0F34 */ OP_NONE,
/* 0F35 */ OP_NONE,
/* 0F36 */ OP_INVALID,
/* 0F37 */ OP_NONE,
/* 0F38 */ OP_MODRM | OP_EXTENDED,
/* 0F39 */ OP_INVALID,
/* 0F3A */ OP_MODRM | OP_EXTENDED | OP_DATA_I8,
/* 0F3B */ OP_INVALID,
/* 0F3C */ OP_INVALID,
/* 0F3D */ OP_INVALID,
/* 0F3E */ OP_INVALID,
/* 0F3F */ OP_INVALID,
/* 0F40 */ OP_MODRM,
/* 0F41 */ OP_MODRM,
/* 0F42 */ OP_MODRM,
/* 0F43 */ OP_MODRM,
/* 0F44 */ OP_MODRM,
/* 0F45 */ OP_MODRM,
/* 0F46 */ OP_MODRM,
/* 0F47 */ OP_MODRM,
/* 0F48 */ OP_MODRM,
/* 0F49 */ OP_MODRM,
/* 0F4A */ OP_MODRM,
/* 0F4B */ OP_MODRM,
/* 0F4C */ OP_MODRM,
/* 0F4D */ OP_MODRM,
/* 0F4E */ OP_MODRM,
/* 0F4F */ OP_MODRM,
/* 0F50 */ OP_MODRM,
/* 0F51 */ OP_MODRM,
/* 0F52 */ OP_MODRM,
/* 0F53 */ OP_MODRM,
/* 0F54 */ OP_MODRM,
/* 0F55 */ OP_MODRM,
/* 0F56 */ OP_MODRM,
/* 0F57 */ OP_MODRM,
/* 0F58 */ OP_MODRM,
/* 0F59 */ OP_MODRM,
/* 0F5A */ OP_MODRM,
/* 0F5B */ OP_MODRM,
/* 0F5C */ OP_MODRM,
/* 0F5D */ OP_MODRM,
/* 0F5E */ OP_MODRM,
/* 0F5F */ OP_MODRM,
/* 0F60 */ OP_MODRM,
/* 0F61 */ OP_MODRM,
/* 0F62 */ OP_MODRM,
/* 0F63 */ OP_MODRM,
/* 0F64 */ OP_MODRM,
/* 0F65 */ OP_MODRM,
/* 0F66 */ OP_MODRM,
/* 0F67 */ OP_MODRM,
/* 0F68 */ OP_MODRM,
/* 0F69 */ OP_MODRM,
/* 0F6A */ OP_MODRM,
/* 0F6B */ OP_MODRM,
/* 0F6C */ OP_MODRM,
/* 0F6D */ OP_MODRM,
/* 0F6E */ OP_MODRM,
/* 0F6F */ OP_MODRM,
/* 0F70 */ OP_MODRM | OP_DATA_I8,
/* 0F71 */ OP_MODRM | OP_DATA_I8,
/* 0F72 */ OP_MODRM | OP_DATA_I8,
/* 0F73 */ OP_MODRM | OP_DATA_I8,
/* 0F74 */ OP_MODRM,
/* 0F75 */ OP_MODRM,
/* 0F76 */ OP_MODRM,
/* 0F77 */ OP_NONE,
/* 0F78 */ OP_MODRM,
/* 0F79 */ OP_MODRM,
/* 0F7A */ OP_INVALID,
/* 0F7B */ OP_INVALID,
/* 0F7C */ OP_MODRM,
/* 0F7D */ OP_MODRM,
/* 0F7E */ OP_MODRM,
/* 0F7F */ OP_MODRM,
/* 0F80 */ OP_RELATIVE | OP_DATA_I16_I32,
/* 0F81 */ OP_RELATIVE | OP_DATA_I16_I32,
/* 0F82 */ OP_RELATIVE | OP_DATA_I16_I32,
/* 0F83 */ OP_RELATIVE | OP_DATA_I16_I32,
/* 0F84 */ OP_RELATIVE | OP_DATA_I16_I32,
/* 0F85 */ OP_RELATIVE | OP_DATA_I16_I32,
/* 0F86 */ OP_RELATIVE | OP_DATA_I16_I32,
/* 0F87 */ OP_RELATIVE | OP_DATA_I16_I32,
/* 0F88 */ OP_RELATIVE | OP_DATA_I16_I32,
/* 0F89 */ OP_RELATIVE | OP_DATA_I16_I32,
/* 0F8A */ OP_RELATIVE | OP_DATA_I16_I32,
/* 0F8B */ OP_RELATIVE | OP_DATA_I16_I32,
/* 0F8C */ OP_RELATIVE | OP_DATA_I16_I32,
/* 0F8D */ OP_RELATIVE | OP_DATA_I16_I32,
/* 0F8E */ OP_RELATIVE | OP_DATA_I16_I32,
/* 0F8F */ OP_RELATIVE | OP_DATA_I16_I32,
/* 0F90 */ OP_MODRM,
/* 0F91 */ OP_MODRM,
/* 0F92 */ OP_MODRM,
/* 0F93 */ OP_MODRM,
/* 0F94 */ OP_MODRM,
/* 0F95 */ OP_MODRM,
/* 0F96 */ OP_MODRM,
/* 0F97 */ OP_MODRM,
/* 0F98 */ OP_MODRM,
/* 0F99 */ OP_MODRM,
/* 0F9A */ OP_MODRM,
/* 0F9B */ OP_MODRM,
/* 0F9C */ OP_MODRM,
/* 0F9D */ OP_MODRM,
/* 0F9E */ OP_MODRM,
/* 0F9F */ OP_MODRM,
/* 0FA0 */ OP_NONE,
/* 0FA1 */ OP_NONE,
/* 0FA2 */ OP_NONE,
/* 0FA3 */ OP_MODRM,
/* 0FA4 */ OP_MODRM | OP_DATA_I8,
/* 0FA5 */ OP_MODRM,
/* 0FA6 */ OP_INVALID,
/* 0FA7 */ OP_INVALID,
/* 0FA8 */ OP_NONE,
/* 0FA9 */ OP_NONE,
/* 0FAA */ OP_NONE,
/* 0FAB */ OP_MODRM,
/* 0FAC */ OP_MODRM | OP_DATA_I8,
/* 0FAD */ OP_MODRM,
/* 0FAE */ OP_MODRM,
/* 0FAF */ OP_MODRM,
/* 0FB0 */ OP_MODRM,
/* 0FB1 */ OP_MODRM,
/* 0FB2 */ OP_MODRM,
/* 0FB3 */ OP_MODRM,
/* 0FB4 */ OP_MODRM,
/* 0FB5 */ OP_MODRM,
/* 0FB6 */ OP_MODRM,
/* 0FB7 */ OP_MODRM,
/* 0FB8 */ OP_MODRM,
/* 0FB9 */ OP_MODRM,
/* 0FBA */ OP_MODRM | OP_DATA_I8,
/* 0FBB */ OP_MODRM,
/* 0FBC */ OP_MODRM,
/* 0FBD */ OP_MODRM,
/* 0FBE */ OP_MODRM,
/* 0FBF */ OP_MODRM,
/* 0FC0 */ OP_MODRM,
/* 0FC1 */ OP_MODRM,
/* 0FC2 */ OP_MODRM | OP_DATA_I8,
/* 0FC3 */ OP_MODRM,
/* 0FC4 */ OP_MODRM | OP_DATA_I8,
/* 0FC5 */ OP_MODRM | OP_DATA_I8,
/* 0FC6 */ OP_MODRM | OP_DATA_I8,
/* 0FC7 */ OP_MODRM,
/* 0FC8 */ OP_NONE,
/* 0FC9 */ OP_NONE,
/* 0FCA */ OP_NONE,
/* 0FCB */ OP_NONE,
/* 0FCC */ OP_NONE,
/* 0FCD */ OP_NONE,
/* 0FCE */ OP_NONE,
/* 0FCF */ OP_NONE,
/* 0FD0 */ OP_MODRM,
/* 0FD1 */ OP_MODRM,
/* 0FD2 */ OP_MODRM,
/* 0FD3 */ OP_MODRM,
/* 0FD4 */ OP_MODRM,
/* 0FD5 */ OP_MODRM,
/* 0FD6 */ OP_MODRM,
/* 0FD7 */ OP_MODRM,
/* 0FD8 */ OP_MODRM,
/* 0FD9 */ OP_MODRM,
/* 0FDA */ OP_MODRM,
/* 0FDB */ OP_MODRM,
/* 0FDC */ OP_MODRM,
/* 0FDD */ OP_MODRM,
/* 0FDE */ OP_MODRM,
/* 0FDF */ OP_MODRM,
/* 0FE0 */ OP_MODRM,
/* 0FE1 */ OP_MODRM,
/* 0FE2 */ OP_MODRM,
/* 0FE3 */ OP_MODRM,
/* 0FE4 */ OP_MODRM,
/* 0FE5 */ OP_MODRM,
/* 0FE6 */ OP_MODRM,
/* 0FE7 */ OP_MODRM,
/* 0FE8 */ OP_MODRM,
/* 0FE9 */ OP_MODRM,
/* 0FEA */ OP_MODRM,
/* 0FEB */ OP_MODRM,
/* 0FEC */ OP_MODRM,
/* 0FED */ OP_MODRM,
/* 0FEE */ OP_MODRM,
/* 0FEF */ OP_MODRM,
/* 0FF0 */ OP_MODRM,
/* 0FF1 */ OP_MODRM,
/* 0FF2 */ OP_MODRM,
/* 0FF3 */ OP_MODRM,
/* 0FF4 */ OP_MODRM,
/* 0FF5 */ OP_MODRM,
/* 0FF6 */ OP_MODRM,
/* 0FF7 */ OP_MODRM,
/* 0FF8 */ OP_MODRM,
/* 0FF9 */ OP_MODRM,
/* 0FFA */ OP_MODRM,
/* 0FFB */ OP_MODRM,
/* 0FFC */ OP_MODRM,
/* 0FFD */ OP_MODRM,
/* 0FFE */ OP_MODRM,
/* 0FFF */ OP_INVALID,
};
static byte cflags(byte op)
{
return flags_table[op];
}
static byte cflags_ex(byte op)
{
return flags_table_ex[op];
}
/// <summary>
/// 计算大于等于 size 字节的最少指令的长度
/// </summary>
/// <param name="code"></param>
/// <returns></returns>
public static uint SizeofMinNumByte(void* code, int size)
{
if (IsARM())
return (uint)((size + 3) / 4) * 4; // 此为 jit 模式下的长度,不再支持 thumb
uint Length;
byte* pOpcode;
uint Result = 0;
ldasm_data data = new ldasm_data();
bool is64 = IntPtr.Size == 8;
do
{
Length = ldasm(code, data, is64);
pOpcode = (byte*)code + data.opcd_offset;
Result += Length;
if (Result >= size)
break;
if ((Length == 1) && (*pOpcode == 0xCC))
break;
code = (void*)((ulong)code + Length);
} while (Length>0);
return Result;
}
static bool? s_isArm;
public static bool IsARM()
{
if(s_isArm.HasValue)
return s_isArm.Value;
string processorType = UnityEngine.SystemInfo.processorType;
/*
* appple M
* SystemInfo.processorType : Apple M1 Max, Apple M2
* SystemInfo.operatingSystem : Mac OS X xx.x.x
*
*/
s_isArm = processorType.Contains("ARM") || processorType.Contains("Apple M");
return s_isArm.Value;
}
public static bool IsArm32()
{
return IsARM() && IntPtr.Size == 4;
}
public static bool IsArm64()
{
return IsARM() && IntPtr.Size == 8;
}
static bool? s_isiOS;
public static bool IsiOS()
{
if(s_isiOS.HasValue)
return s_isiOS.Value;
s_isiOS = UnityEngine.SystemInfo.operatingSystem.ToLower().Contains("ios");
return s_isiOS.Value;
}
static bool? s_isIL2CPP;
public static bool IsIL2CPP()
{
if (s_isIL2CPP.HasValue)
return s_isIL2CPP.Value;
try
{
byte[] ilBody = typeof(LDasm).GetMethod("IsIL2CPP").GetMethodBody().GetILAsByteArray();
if (ilBody == null || ilBody.Length == 0)
s_isIL2CPP = true;
else
s_isIL2CPP = false;
}
catch
{
s_isIL2CPP = true;
}
return s_isIL2CPP.Value;
}
public static bool IsThumb(IntPtr code)
{
return IsArm32() && ((long)code & 0x1) == 0x1;
}
/// <summary>
/// 计算 thumb 指令长度
/// </summary>
/// <param name="code"></param>
/// <param name="size"></param>
/// <returns></returns>
public static uint CalcARMThumbMinLen(void* code, int size)
{
uint len = 0;
ushort* ins = (ushort*)code;
while (true)
{
if (len >= size)
return len;
if (((*ins >> 13) & 3) == 3)
{
ins += 2;
len += 4;
}
else
{
ins++;
len += 2;
}
}
}
static uint ldasm(void* code, ldasm_data ld, bool is64)
{
byte* p = (byte*)code;
byte s, op, f;
byte rexw, pr_66, pr_67;
s = rexw = pr_66 = pr_67 = 0;
/* dummy check */
if ((int)code==0)
return 0;
/* init output data */
//memset(ld, 0, sizeof(ldasm_data));
/* phase 1: parse prefixies */
while ((cflags(*p) & OP_PREFIX)!=0)
{
if (*p == 0x66)
pr_66 = 1;
if (*p == 0x67)
pr_67 = 1;
p++; s++;
ld.flags |= F_PREFIX;
if (s == 15)
{
ld.flags |= F_INVALID;
return s;
}
}
/* parse REX prefix */
if (is64 && *p >> 4 == 4)
{
ld.rex = *p;
rexw = (byte)((ld.rex >> 3) & 1);
ld.flags |= F_REX;
p++; s++;
}
/* can be only one REX prefix */
if (is64 && *p >> 4 == 4)
{
ld.flags |= F_INVALID;
s++;
return s;
}
/* phase 2: parse opcode */
ld.opcd_offset = (byte)(p - (byte*)code);
ld.opcd_size = 1;
op = *p++; s++;
/* is 2 byte opcode? */
if (op == 0x0F)
{
op = *p++; s++;
ld.opcd_size++;
f = cflags_ex(op);
if ((f & OP_INVALID)!=0)
{
ld.flags |= F_INVALID;
return s;
}
/* for SSE instructions */
if ((f & OP_EXTENDED)!=0)
{
op = *p++; s++;
ld.opcd_size++;
}
}
else {
f = cflags(op);
/* pr_66 = pr_67 for opcodes A0-A3 */
if (op >= 0xA0 && op <= 0xA3)
pr_66 = pr_67;
}
/* phase 3: parse ModR/M, SIB and DISP */
if ((f & OP_MODRM)!=0)
{
byte mod = (byte)(*p >> 6);
byte ro = (byte)((*p & 0x38) >> 3);
byte rm = (byte)(*p & 7);
ld.modrm = *p++; s++;
ld.flags |= F_MODRM;
/* in F6,F7 opcodes immediate data present if R/O == 0 */
if (op == 0xF6 && (ro == 0 || ro == 1))
f |= OP_DATA_I8;
if (op == 0xF7 && (ro == 0 || ro == 1))
f |= OP_DATA_I16_I32_I64;
/* is SIB byte exist? */
if (mod != 3 && rm == 4 && !(!is64 && pr_67!=0))
{
ld.sib = *p++; s++;
ld.flags |= F_SIB;
/* if base == 5 and mod == 0 */
if ((ld.sib & 7) == 5 && mod == 0)
{
ld.disp_size = 4;
}
}
switch (mod)
{
case 0:
if (is64)
{
if (rm == 5)
{
ld.disp_size = 4;
if (is64)
ld.flags |= F_RELATIVE;
}
}
else if (pr_67!=0)
{
if (rm == 6)
ld.disp_size = 2;
}
else {
if (rm == 5)
ld.disp_size = 4;
}
break;
case 1:
ld.disp_size = 1;
break;
case 2:
if (is64)
ld.disp_size = 4;
else if (pr_67!=0)
ld.disp_size = 2;
else
ld.disp_size = 4;
break;
}
if (ld.disp_size>0)
{
ld.disp_offset = (byte)(p - (byte*)code);
p += ld.disp_size;
s += ld.disp_size;
ld.flags |= F_DISP;
}
}
/* phase 4: parse immediate data */
if (rexw!=0 && (f & OP_DATA_I16_I32_I64)!=0)
ld.imm_size = 8;
else if ((f & OP_DATA_I16_I32)!=0 || (f & OP_DATA_I16_I32_I64)!=0)
ld.imm_size = (byte)(4 - (pr_66 << 1));
/* if exist, add OP_DATA_I16 and OP_DATA_I8 size */
ld.imm_size += (byte)(f & 3);
if ((ld.imm_size)!=0)
{
s += ld.imm_size;
ld.imm_offset = (byte)(p - (byte*)code);
ld.flags |= F_IMM;
if ((f & OP_RELATIVE)!=0)
ld.flags |= F_RELATIVE;
}
/* instruction is too long */
if (s > 15)
ld.flags |= F_INVALID;
return s;
}
}
}