github.com/tencent/goom@v1.0.1/internal/arch/x86asm/inst.go (about)

     1  // Copyright 2014 The Go Authors.  All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // Package x86asm implements decoding of x86 machine code.
     6  package x86asm
     7  
     8  import (
     9  	"bytes"
    10  	"fmt"
    11  )
    12  
    13  // Inst is a single instruction.
    14  type Inst struct {
    15  	Prefix   Prefixes // Prefixes applied to the instruction.
    16  	Op       Op       // Opcode mnemonic
    17  	Opcode   uint32   // Encoded opcode bits, left aligned (first byte is Opcode>>24, etc)
    18  	Args     Args     // Instruction arguments, in Intel order
    19  	Mode     int      // processor mode in bits: 16, 32, or 64
    20  	AddrSize int      // address size in bits: 16, 32, or 64
    21  	DataSize int      // operand size in bits: 16, 32, or 64
    22  	MemBytes int      // size of memory argument in bytes: 1, 2, 4, 8, 16, and so on.
    23  	Len      int      // length of encoded instruction in bytes
    24  	PCRel    int      // length of PC-relative address in instruction encoding
    25  	PCRelOff int      // index of start of PC-relative address in instruction encoding
    26  }
    27  
    28  // Prefixes is an array of prefixes associated with a single instruction.
    29  // The prefixes are listed in the same order as found in the instruction:
    30  // each prefix byte corresponds to one slot in the array. The first zero
    31  // in the array marks the end of the prefixes.
    32  type Prefixes [14]Prefix
    33  
    34  // Prefix represents an Intel instruction prefix.
    35  // The low 8 bits are the actual prefix byte encoding,
    36  // and the top 8 bits contain distinguishing bits and metadata.
    37  type Prefix uint16
    38  
    39  // nolint
    40  const (
    41  	// Metadata about the role of a prefix in an instruction.
    42  	PrefixImplicit Prefix = 0x8000 // prefix is implied by instruction text
    43  	PrefixIgnored  Prefix = 0x4000 // prefix is ignored: either irrelevant or overridden by a later prefix
    44  	PrefixInvalid  Prefix = 0x2000 // prefix makes entire instruction invalid (bad LOCK)
    45  
    46  	// nolint
    47  	// Memory segment overrides.
    48  	PrefixES Prefix = 0x26 // ES segment override
    49  	PrefixCS Prefix = 0x2E // CS segment override
    50  	PrefixSS Prefix = 0x36 // SS segment override
    51  	PrefixDS Prefix = 0x3E // DS segment override
    52  	PrefixFS Prefix = 0x64 // FS segment override
    53  	PrefixGS Prefix = 0x65 // GS segment override
    54  
    55  	// PrefixPN Branch prediction.
    56  	PrefixPN Prefix = 0x12E // predict not taken (conditional branch only)
    57  	PrefixPT Prefix = 0x13E // predict taken (conditional branch only)
    58  
    59  	// nolint
    60  	// Size attributes.
    61  	PrefixDataSize Prefix = 0x66 // operand size override
    62  	PrefixData16   Prefix = 0x166
    63  	PrefixData32   Prefix = 0x266
    64  	PrefixAddrSize Prefix = 0x67 // address size override
    65  	PrefixAddr16   Prefix = 0x167
    66  	PrefixAddr32   Prefix = 0x267
    67  
    68  	// PrefixLOCK One of a kind.
    69  	PrefixLOCK     Prefix = 0xF0 // lock
    70  	PrefixREPN     Prefix = 0xF2 // repeat not zero
    71  	PrefixXACQUIRE Prefix = 0x1F2
    72  	PrefixBND      Prefix = 0x2F2
    73  	PrefixREP      Prefix = 0xF3 // repeat
    74  	PrefixXRELEASE Prefix = 0x1F3
    75  
    76  	// PrefixREX The REX prefixes must be in the range [PrefixREX, PrefixREX+0x10).
    77  	// the other bits are set or not according to the intended use.
    78  	PrefixREX       Prefix = 0x40 // REX 64-bit extension prefix
    79  	PrefixREXW      Prefix = 0x08 // extension bit W (64-bit instruction width)
    80  	PrefixREXR      Prefix = 0x04 // extension bit R (r field in modrm)
    81  	PrefixREXX      Prefix = 0x02 // extension bit X (index field in sib)
    82  	PrefixREXB      Prefix = 0x01 // extension bit B (r/m field in modrm or base field in sib)
    83  	PrefixVEX2Bytes Prefix = 0xC5 // Short form of vex prefix
    84  	PrefixVEX3Bytes Prefix = 0xC4 // Long form of vex prefix
    85  )
    86  
    87  // IsREX reports whether p is a REX prefix byte.
    88  func (p Prefix) IsREX() bool {
    89  	return p&0xF0 == PrefixREX
    90  }
    91  
    92  // IsVEX reports whether p is a VEX prefix byte.
    93  func (p Prefix) IsVEX() bool {
    94  	return p&0xFF == PrefixVEX2Bytes || p&0xFF == PrefixVEX3Bytes
    95  }
    96  
    97  // String to string
    98  // nolint
    99  func (p Prefix) String() string {
   100  	p &^= PrefixImplicit | PrefixIgnored | PrefixInvalid
   101  	if s := prefixNames[p]; s != "" {
   102  		return s
   103  	}
   104  
   105  	if p.IsREX() {
   106  		s := "REX."
   107  		if p&PrefixREXW != 0 {
   108  			s += "W"
   109  		}
   110  
   111  		if p&PrefixREXR != 0 {
   112  			s += "R"
   113  		}
   114  
   115  		if p&PrefixREXX != 0 {
   116  			s += "X"
   117  		}
   118  
   119  		if p&PrefixREXB != 0 {
   120  			s += "B"
   121  		}
   122  
   123  		return s
   124  	}
   125  
   126  	return fmt.Sprintf("Prefix(%#x)", int(p))
   127  }
   128  
   129  // Op is an x86 opcode.
   130  type Op uint32
   131  
   132  // String to string
   133  // noLint
   134  func (op Op) String() string {
   135  	i := int(op)
   136  	if i < 0 || i >= len(opNames) || opNames[i] == "" {
   137  		return fmt.Sprintf("Op(%d)", i)
   138  	}
   139  
   140  	return opNames[i]
   141  }
   142  
   143  // Args holds the instruction arguments.
   144  // If an instruction has fewer than 4 arguments,
   145  // the final elements in the array are nil.
   146  type Args [4]Arg
   147  
   148  // Arg is a single instruction argument,
   149  // one of these types: Reg, Mem, Imm, Rel.
   150  type Arg interface {
   151  	// String to string
   152  	String() string
   153  	isArg()
   154  }
   155  
   156  // Note that the implements of Arg that follow are all sized
   157  // so that on a 64-bit machine the data can be inlined in
   158  // the interface value instead of requiring an allocation.
   159  
   160  // Reg is a single register.
   161  // The zero Reg value has no name but indicates “no register.”
   162  type Reg uint8
   163  
   164  // nolint
   165  const (
   166  	_ Reg = iota
   167  
   168  	// AL 8-bit
   169  	AL
   170  	CL
   171  	DL
   172  	BL
   173  	AH
   174  	CH
   175  	DH
   176  	BH
   177  	SPB
   178  	BPB
   179  	SIB
   180  	DIB
   181  	R8B
   182  	R9B
   183  	R10B
   184  	R11B
   185  	R12B
   186  	R13B
   187  	R14B
   188  	R15B
   189  
   190  	// AX 16-bit
   191  	AX
   192  	CX
   193  	DX
   194  	BX
   195  	SP
   196  	BP
   197  	SI
   198  	DI
   199  	R8W
   200  	R9W
   201  	R10W
   202  	R11W
   203  	R12W
   204  	R13W
   205  	R14W
   206  	R15W
   207  
   208  	// EAX 32-bit
   209  	EAX
   210  	ECX
   211  	EDX
   212  	EBX
   213  	ESP
   214  	EBP
   215  	ESI
   216  	EDI
   217  	R8L
   218  	R9L
   219  	R10L
   220  	R11L
   221  	R12L
   222  	R13L
   223  	R14L
   224  	R15L
   225  
   226  	// RAX 64-bit
   227  	RAX
   228  	RCX
   229  	RDX
   230  	RBX
   231  	RSP
   232  	RBP
   233  	RSI
   234  	RDI
   235  	R8
   236  	R9
   237  	R10
   238  	R11
   239  	R12
   240  	R13
   241  	R14
   242  	R15
   243  
   244  	// nolint
   245  	// Instruction pointer.
   246  	IP  // 16-bit
   247  	EIP // 32-bit
   248  	RIP // 64-bit
   249  
   250  	// F0 387 floating point registers.
   251  	F0
   252  	F1
   253  	F2
   254  	F3
   255  	F4
   256  	F5
   257  	F6
   258  	F7
   259  
   260  	// nolint
   261  	// MMX registers.
   262  	M0
   263  	M1
   264  	M2
   265  	M3
   266  	M4
   267  	M5
   268  	M6
   269  	M7
   270  
   271  	// nolint
   272  	// XMM registers.
   273  	X0
   274  	X1
   275  	X2
   276  	X3
   277  	X4
   278  	X5
   279  	X6
   280  	X7
   281  	X8
   282  	X9
   283  	X10
   284  	X11
   285  	X12
   286  	X13
   287  	X14
   288  	X15
   289  
   290  	// nolint
   291  	// Segment registers.
   292  	ES
   293  	CS
   294  	SS
   295  	DS
   296  	FS
   297  	GS
   298  
   299  	// nolint
   300  	// System registers.
   301  	GDTR
   302  	IDTR
   303  	LDTR
   304  	MSW
   305  	TASK
   306  
   307  	// CR0 Control registers.
   308  	CR0
   309  	CR1
   310  	CR2
   311  	CR3
   312  	CR4
   313  	CR5
   314  	CR6
   315  	CR7
   316  	CR8
   317  	CR9
   318  	CR10
   319  	CR11
   320  	CR12
   321  	CR13
   322  	CR14
   323  	CR15
   324  
   325  	// DR0 Debug registers.
   326  	DR0
   327  	DR1
   328  	DR2
   329  	DR3
   330  	DR4
   331  	DR5
   332  	DR6
   333  	DR7
   334  	DR8
   335  	DR9
   336  	DR10
   337  	DR11
   338  	DR12
   339  	DR13
   340  	DR14
   341  	DR15
   342  
   343  	// TR0 Task registers.
   344  	TR0
   345  	TR1
   346  	TR2
   347  	TR3
   348  	TR4
   349  	TR5
   350  	TR6
   351  	TR7
   352  )
   353  
   354  const regMax = TR7
   355  
   356  // noLint
   357  func (Reg) isArg() {}
   358  
   359  // String to string
   360  // noLint
   361  func (r Reg) String() string {
   362  	i := int(r)
   363  	if i < 0 || i >= len(regNames) || regNames[i] == "" {
   364  		return fmt.Sprintf("Reg(%d)", i)
   365  	}
   366  
   367  	return regNames[i]
   368  }
   369  
   370  // Mem is a memory reference.
   371  // The general form is Segment:[Base+Scale*Index+Disp].
   372  type Mem struct {
   373  	Segment Reg
   374  	Base    Reg
   375  	Scale   uint8
   376  	Index   Reg
   377  	Disp    int64
   378  }
   379  
   380  // noLint
   381  func (Mem) isArg() {}
   382  
   383  // String to string
   384  // noLint
   385  func (m Mem) String() string {
   386  	var base, plus, scale, index, disp string
   387  
   388  	if m.Base != 0 {
   389  		base = m.Base.String()
   390  	}
   391  
   392  	if m.Scale != 0 {
   393  		if m.Base != 0 {
   394  			plus = "+"
   395  		}
   396  
   397  		if m.Scale > 1 {
   398  			scale = fmt.Sprintf("%d*", m.Scale)
   399  		}
   400  
   401  		index = m.Index.String()
   402  	}
   403  
   404  	if m.Disp != 0 || m.Base == 0 && m.Scale == 0 {
   405  		disp = fmt.Sprintf("%+#x", m.Disp)
   406  	}
   407  
   408  	return "[" + base + plus + scale + index + disp + "]"
   409  }
   410  
   411  // Rel is an offset relative to the current instruction pointer.
   412  type Rel int32
   413  
   414  // noLint
   415  func (Rel) isArg() {}
   416  
   417  // String to string
   418  // noLint
   419  func (r Rel) String() string {
   420  	return fmt.Sprintf(".%+d", r)
   421  }
   422  
   423  // Imm is an integer constant.
   424  type Imm int64
   425  
   426  // noLint
   427  func (Imm) isArg() {}
   428  
   429  // String to string
   430  // noLint
   431  func (i Imm) String() string {
   432  	return fmt.Sprintf("%#x", int64(i))
   433  }
   434  
   435  // String to strings
   436  // noLint
   437  func (i Inst) String() string {
   438  	var buf bytes.Buffer
   439  
   440  	for _, p := range i.Prefix {
   441  		if p == 0 {
   442  			break
   443  		}
   444  
   445  		if p&PrefixImplicit != 0 {
   446  			continue
   447  		}
   448  
   449  		fmt.Fprintf(&buf, "%v ", p)
   450  	}
   451  
   452  	fmt.Fprintf(&buf, "%v", i.Op)
   453  
   454  	sep := " "
   455  
   456  	for _, v := range i.Args {
   457  		if v == nil {
   458  			break
   459  		}
   460  
   461  		fmt.Fprintf(&buf, "%s%v", sep, v)
   462  		sep = ", "
   463  	}
   464  
   465  	return buf.String()
   466  }
   467  
   468  // noLint
   469  func isMem(a Arg) bool {
   470  	_, ok := a.(Mem)
   471  	return ok
   472  }
   473  
   474  // The Op definitions and string list are in tables.go.
   475  
   476  var prefixNames = map[Prefix]string{
   477  	PrefixCS:       "CS",
   478  	PrefixDS:       "DS",
   479  	PrefixES:       "ES",
   480  	PrefixFS:       "FS",
   481  	PrefixGS:       "GS",
   482  	PrefixSS:       "SS",
   483  	PrefixLOCK:     "LOCK",
   484  	PrefixREP:      "REP",
   485  	PrefixREPN:     "REPN",
   486  	PrefixAddrSize: "ADDRSIZE",
   487  	PrefixDataSize: "DATASIZE",
   488  	PrefixAddr16:   "ADDR16",
   489  	PrefixData16:   "DATA16",
   490  	PrefixAddr32:   "ADDR32",
   491  	PrefixData32:   "DATA32",
   492  	PrefixBND:      "BND",
   493  	PrefixXACQUIRE: "XACQUIRE",
   494  	PrefixXRELEASE: "XRELEASE",
   495  	PrefixREX:      "REX",
   496  	PrefixPT:       "PT",
   497  	PrefixPN:       "PN",
   498  }
   499  
   500  var regNames = [...]string{
   501  	AL:   "AL",
   502  	CL:   "CL",
   503  	BL:   "BL",
   504  	DL:   "DL",
   505  	AH:   "AH",
   506  	CH:   "CH",
   507  	BH:   "BH",
   508  	DH:   "DH",
   509  	SPB:  "SPB",
   510  	BPB:  "BPB",
   511  	SIB:  "SIB",
   512  	DIB:  "DIB",
   513  	R8B:  "R8B",
   514  	R9B:  "R9B",
   515  	R10B: "R10B",
   516  	R11B: "R11B",
   517  	R12B: "R12B",
   518  	R13B: "R13B",
   519  	R14B: "R14B",
   520  	R15B: "R15B",
   521  	AX:   "AX",
   522  	CX:   "CX",
   523  	BX:   "BX",
   524  	DX:   "DX",
   525  	SP:   "SP",
   526  	BP:   "BP",
   527  	SI:   "SI",
   528  	DI:   "DI",
   529  	R8W:  "R8W",
   530  	R9W:  "R9W",
   531  	R10W: "R10W",
   532  	R11W: "R11W",
   533  	R12W: "R12W",
   534  	R13W: "R13W",
   535  	R14W: "R14W",
   536  	R15W: "R15W",
   537  	EAX:  "EAX",
   538  	ECX:  "ECX",
   539  	EDX:  "EDX",
   540  	EBX:  "EBX",
   541  	ESP:  "ESP",
   542  	EBP:  "EBP",
   543  	ESI:  "ESI",
   544  	EDI:  "EDI",
   545  	R8L:  "R8L",
   546  	R9L:  "R9L",
   547  	R10L: "R10L",
   548  	R11L: "R11L",
   549  	R12L: "R12L",
   550  	R13L: "R13L",
   551  	R14L: "R14L",
   552  	R15L: "R15L",
   553  	RAX:  "RAX",
   554  	RCX:  "RCX",
   555  	RDX:  "RDX",
   556  	RBX:  "RBX",
   557  	RSP:  "RSP",
   558  	RBP:  "RBP",
   559  	RSI:  "RSI",
   560  	RDI:  "RDI",
   561  	R8:   "R8",
   562  	R9:   "R9",
   563  	R10:  "R10",
   564  	R11:  "R11",
   565  	R12:  "R12",
   566  	R13:  "R13",
   567  	R14:  "R14",
   568  	R15:  "R15",
   569  	IP:   "IP",
   570  	EIP:  "EIP",
   571  	RIP:  "RIP",
   572  	F0:   "F0",
   573  	F1:   "F1",
   574  	F2:   "F2",
   575  	F3:   "F3",
   576  	F4:   "F4",
   577  	F5:   "F5",
   578  	F6:   "F6",
   579  	F7:   "F7",
   580  	M0:   "M0",
   581  	M1:   "M1",
   582  	M2:   "M2",
   583  	M3:   "M3",
   584  	M4:   "M4",
   585  	M5:   "M5",
   586  	M6:   "M6",
   587  	M7:   "M7",
   588  	X0:   "X0",
   589  	X1:   "X1",
   590  	X2:   "X2",
   591  	X3:   "X3",
   592  	X4:   "X4",
   593  	X5:   "X5",
   594  	X6:   "X6",
   595  	X7:   "X7",
   596  	X8:   "X8",
   597  	X9:   "X9",
   598  	X10:  "X10",
   599  	X11:  "X11",
   600  	X12:  "X12",
   601  	X13:  "X13",
   602  	X14:  "X14",
   603  	X15:  "X15",
   604  	CS:   "CS",
   605  	SS:   "SS",
   606  	DS:   "DS",
   607  	ES:   "ES",
   608  	FS:   "FS",
   609  	GS:   "GS",
   610  	GDTR: "GDTR",
   611  	IDTR: "IDTR",
   612  	LDTR: "LDTR",
   613  	MSW:  "MSW",
   614  	TASK: "TASK",
   615  	CR0:  "CR0",
   616  	CR1:  "CR1",
   617  	CR2:  "CR2",
   618  	CR3:  "CR3",
   619  	CR4:  "CR4",
   620  	CR5:  "CR5",
   621  	CR6:  "CR6",
   622  	CR7:  "CR7",
   623  	CR8:  "CR8",
   624  	CR9:  "CR9",
   625  	CR10: "CR10",
   626  	CR11: "CR11",
   627  	CR12: "CR12",
   628  	CR13: "CR13",
   629  	CR14: "CR14",
   630  	CR15: "CR15",
   631  	DR0:  "DR0",
   632  	DR1:  "DR1",
   633  	DR2:  "DR2",
   634  	DR3:  "DR3",
   635  	DR4:  "DR4",
   636  	DR5:  "DR5",
   637  	DR6:  "DR6",
   638  	DR7:  "DR7",
   639  	DR8:  "DR8",
   640  	DR9:  "DR9",
   641  	DR10: "DR10",
   642  	DR11: "DR11",
   643  	DR12: "DR12",
   644  	DR13: "DR13",
   645  	DR14: "DR14",
   646  	DR15: "DR15",
   647  	TR0:  "TR0",
   648  	TR1:  "TR1",
   649  	TR2:  "TR2",
   650  	TR3:  "TR3",
   651  	TR4:  "TR4",
   652  	TR5:  "TR5",
   653  	TR6:  "TR6",
   654  	TR7:  "TR7",
   655  }