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

910 lines
29 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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;
}
}
}