123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649 |
- // Copyright 2014 The Go Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style
- // license that can be found in the LICENSE file.
- // Package x86asm implements decoding of x86 machine code.
- package x86asm
- import (
- "bytes"
- "fmt"
- )
- // An Inst is a single instruction.
- type Inst struct {
- Prefix Prefixes // Prefixes applied to the instruction.
- Op Op // Opcode mnemonic
- Opcode uint32 // Encoded opcode bits, left aligned (first byte is Opcode>>24, etc)
- Args Args // Instruction arguments, in Intel order
- Mode int // processor mode in bits: 16, 32, or 64
- AddrSize int // address size in bits: 16, 32, or 64
- DataSize int // operand size in bits: 16, 32, or 64
- MemBytes int // size of memory argument in bytes: 1, 2, 4, 8, 16, and so on.
- Len int // length of encoded instruction in bytes
- PCRel int // length of PC-relative address in instruction encoding
- PCRelOff int // index of start of PC-relative address in instruction encoding
- }
- // Prefixes is an array of prefixes associated with a single instruction.
- // The prefixes are listed in the same order as found in the instruction:
- // each prefix byte corresponds to one slot in the array. The first zero
- // in the array marks the end of the prefixes.
- type Prefixes [14]Prefix
- // A Prefix represents an Intel instruction prefix.
- // The low 8 bits are the actual prefix byte encoding,
- // and the top 8 bits contain distinguishing bits and metadata.
- type Prefix uint16
- const (
- // Metadata about the role of a prefix in an instruction.
- PrefixImplicit Prefix = 0x8000 // prefix is implied by instruction text
- PrefixIgnored Prefix = 0x4000 // prefix is ignored: either irrelevant or overridden by a later prefix
- PrefixInvalid Prefix = 0x2000 // prefix makes entire instruction invalid (bad LOCK)
- // Memory segment overrides.
- PrefixES Prefix = 0x26 // ES segment override
- PrefixCS Prefix = 0x2E // CS segment override
- PrefixSS Prefix = 0x36 // SS segment override
- PrefixDS Prefix = 0x3E // DS segment override
- PrefixFS Prefix = 0x64 // FS segment override
- PrefixGS Prefix = 0x65 // GS segment override
- // Branch prediction.
- PrefixPN Prefix = 0x12E // predict not taken (conditional branch only)
- PrefixPT Prefix = 0x13E // predict taken (conditional branch only)
- // Size attributes.
- PrefixDataSize Prefix = 0x66 // operand size override
- PrefixData16 Prefix = 0x166
- PrefixData32 Prefix = 0x266
- PrefixAddrSize Prefix = 0x67 // address size override
- PrefixAddr16 Prefix = 0x167
- PrefixAddr32 Prefix = 0x267
- // One of a kind.
- PrefixLOCK Prefix = 0xF0 // lock
- PrefixREPN Prefix = 0xF2 // repeat not zero
- PrefixXACQUIRE Prefix = 0x1F2
- PrefixBND Prefix = 0x2F2
- PrefixREP Prefix = 0xF3 // repeat
- PrefixXRELEASE Prefix = 0x1F3
- // The REX prefixes must be in the range [PrefixREX, PrefixREX+0x10).
- // the other bits are set or not according to the intended use.
- PrefixREX Prefix = 0x40 // REX 64-bit extension prefix
- PrefixREXW Prefix = 0x08 // extension bit W (64-bit instruction width)
- PrefixREXR Prefix = 0x04 // extension bit R (r field in modrm)
- PrefixREXX Prefix = 0x02 // extension bit X (index field in sib)
- PrefixREXB Prefix = 0x01 // extension bit B (r/m field in modrm or base field in sib)
- PrefixVEX2Bytes Prefix = 0xC5 // Short form of vex prefix
- PrefixVEX3Bytes Prefix = 0xC4 // Long form of vex prefix
- )
- // IsREX reports whether p is a REX prefix byte.
- func (p Prefix) IsREX() bool {
- return p&0xF0 == PrefixREX
- }
- func (p Prefix) IsVEX() bool {
- return p&0xFF == PrefixVEX2Bytes || p&0xFF == PrefixVEX3Bytes
- }
- func (p Prefix) String() string {
- p &^= PrefixImplicit | PrefixIgnored | PrefixInvalid
- if s := prefixNames[p]; s != "" {
- return s
- }
- if p.IsREX() {
- s := "REX."
- if p&PrefixREXW != 0 {
- s += "W"
- }
- if p&PrefixREXR != 0 {
- s += "R"
- }
- if p&PrefixREXX != 0 {
- s += "X"
- }
- if p&PrefixREXB != 0 {
- s += "B"
- }
- return s
- }
- return fmt.Sprintf("Prefix(%#x)", int(p))
- }
- // An Op is an x86 opcode.
- type Op uint32
- func (op Op) String() string {
- i := int(op)
- if i < 0 || i >= len(opNames) || opNames[i] == "" {
- return fmt.Sprintf("Op(%d)", i)
- }
- return opNames[i]
- }
- // An Args holds the instruction arguments.
- // If an instruction has fewer than 4 arguments,
- // the final elements in the array are nil.
- type Args [4]Arg
- // An Arg is a single instruction argument,
- // one of these types: Reg, Mem, Imm, Rel.
- type Arg interface {
- String() string
- isArg()
- }
- // Note that the implements of Arg that follow are all sized
- // so that on a 64-bit machine the data can be inlined in
- // the interface value instead of requiring an allocation.
- // A Reg is a single register.
- // The zero Reg value has no name but indicates “no register.”
- type Reg uint8
- const (
- _ Reg = iota
- // 8-bit
- AL
- CL
- DL
- BL
- AH
- CH
- DH
- BH
- SPB
- BPB
- SIB
- DIB
- R8B
- R9B
- R10B
- R11B
- R12B
- R13B
- R14B
- R15B
- // 16-bit
- AX
- CX
- DX
- BX
- SP
- BP
- SI
- DI
- R8W
- R9W
- R10W
- R11W
- R12W
- R13W
- R14W
- R15W
- // 32-bit
- EAX
- ECX
- EDX
- EBX
- ESP
- EBP
- ESI
- EDI
- R8L
- R9L
- R10L
- R11L
- R12L
- R13L
- R14L
- R15L
- // 64-bit
- RAX
- RCX
- RDX
- RBX
- RSP
- RBP
- RSI
- RDI
- R8
- R9
- R10
- R11
- R12
- R13
- R14
- R15
- // Instruction pointer.
- IP // 16-bit
- EIP // 32-bit
- RIP // 64-bit
- // 387 floating point registers.
- F0
- F1
- F2
- F3
- F4
- F5
- F6
- F7
- // MMX registers.
- M0
- M1
- M2
- M3
- M4
- M5
- M6
- M7
- // XMM registers.
- X0
- X1
- X2
- X3
- X4
- X5
- X6
- X7
- X8
- X9
- X10
- X11
- X12
- X13
- X14
- X15
- // Segment registers.
- ES
- CS
- SS
- DS
- FS
- GS
- // System registers.
- GDTR
- IDTR
- LDTR
- MSW
- TASK
- // Control registers.
- CR0
- CR1
- CR2
- CR3
- CR4
- CR5
- CR6
- CR7
- CR8
- CR9
- CR10
- CR11
- CR12
- CR13
- CR14
- CR15
- // Debug registers.
- DR0
- DR1
- DR2
- DR3
- DR4
- DR5
- DR6
- DR7
- DR8
- DR9
- DR10
- DR11
- DR12
- DR13
- DR14
- DR15
- // Task registers.
- TR0
- TR1
- TR2
- TR3
- TR4
- TR5
- TR6
- TR7
- )
- const regMax = TR7
- func (Reg) isArg() {}
- func (r Reg) String() string {
- i := int(r)
- if i < 0 || i >= len(regNames) || regNames[i] == "" {
- return fmt.Sprintf("Reg(%d)", i)
- }
- return regNames[i]
- }
- // A Mem is a memory reference.
- // The general form is Segment:[Base+Scale*Index+Disp].
- type Mem struct {
- Segment Reg
- Base Reg
- Scale uint8
- Index Reg
- Disp int64
- }
- func (Mem) isArg() {}
- func (m Mem) String() string {
- var base, plus, scale, index, disp string
- if m.Base != 0 {
- base = m.Base.String()
- }
- if m.Scale != 0 {
- if m.Base != 0 {
- plus = "+"
- }
- if m.Scale > 1 {
- scale = fmt.Sprintf("%d*", m.Scale)
- }
- index = m.Index.String()
- }
- if m.Disp != 0 || m.Base == 0 && m.Scale == 0 {
- disp = fmt.Sprintf("%+#x", m.Disp)
- }
- return "[" + base + plus + scale + index + disp + "]"
- }
- // A Rel is an offset relative to the current instruction pointer.
- type Rel int32
- func (Rel) isArg() {}
- func (r Rel) String() string {
- return fmt.Sprintf(".%+d", r)
- }
- // An Imm is an integer constant.
- type Imm int64
- func (Imm) isArg() {}
- func (i Imm) String() string {
- return fmt.Sprintf("%#x", int64(i))
- }
- func (i Inst) String() string {
- var buf bytes.Buffer
- for _, p := range i.Prefix {
- if p == 0 {
- break
- }
- if p&PrefixImplicit != 0 {
- continue
- }
- fmt.Fprintf(&buf, "%v ", p)
- }
- fmt.Fprintf(&buf, "%v", i.Op)
- sep := " "
- for _, v := range i.Args {
- if v == nil {
- break
- }
- fmt.Fprintf(&buf, "%s%v", sep, v)
- sep = ", "
- }
- return buf.String()
- }
- func isReg(a Arg) bool {
- _, ok := a.(Reg)
- return ok
- }
- func isSegReg(a Arg) bool {
- r, ok := a.(Reg)
- return ok && ES <= r && r <= GS
- }
- func isMem(a Arg) bool {
- _, ok := a.(Mem)
- return ok
- }
- func isImm(a Arg) bool {
- _, ok := a.(Imm)
- return ok
- }
- func regBytes(a Arg) int {
- r, ok := a.(Reg)
- if !ok {
- return 0
- }
- if AL <= r && r <= R15B {
- return 1
- }
- if AX <= r && r <= R15W {
- return 2
- }
- if EAX <= r && r <= R15L {
- return 4
- }
- if RAX <= r && r <= R15 {
- return 8
- }
- return 0
- }
- func isSegment(p Prefix) bool {
- switch p {
- case PrefixCS, PrefixDS, PrefixES, PrefixFS, PrefixGS, PrefixSS:
- return true
- }
- return false
- }
- // The Op definitions and string list are in tables.go.
- var prefixNames = map[Prefix]string{
- PrefixCS: "CS",
- PrefixDS: "DS",
- PrefixES: "ES",
- PrefixFS: "FS",
- PrefixGS: "GS",
- PrefixSS: "SS",
- PrefixLOCK: "LOCK",
- PrefixREP: "REP",
- PrefixREPN: "REPN",
- PrefixAddrSize: "ADDRSIZE",
- PrefixDataSize: "DATASIZE",
- PrefixAddr16: "ADDR16",
- PrefixData16: "DATA16",
- PrefixAddr32: "ADDR32",
- PrefixData32: "DATA32",
- PrefixBND: "BND",
- PrefixXACQUIRE: "XACQUIRE",
- PrefixXRELEASE: "XRELEASE",
- PrefixREX: "REX",
- PrefixPT: "PT",
- PrefixPN: "PN",
- }
- var regNames = [...]string{
- AL: "AL",
- CL: "CL",
- BL: "BL",
- DL: "DL",
- AH: "AH",
- CH: "CH",
- BH: "BH",
- DH: "DH",
- SPB: "SPB",
- BPB: "BPB",
- SIB: "SIB",
- DIB: "DIB",
- R8B: "R8B",
- R9B: "R9B",
- R10B: "R10B",
- R11B: "R11B",
- R12B: "R12B",
- R13B: "R13B",
- R14B: "R14B",
- R15B: "R15B",
- AX: "AX",
- CX: "CX",
- BX: "BX",
- DX: "DX",
- SP: "SP",
- BP: "BP",
- SI: "SI",
- DI: "DI",
- R8W: "R8W",
- R9W: "R9W",
- R10W: "R10W",
- R11W: "R11W",
- R12W: "R12W",
- R13W: "R13W",
- R14W: "R14W",
- R15W: "R15W",
- EAX: "EAX",
- ECX: "ECX",
- EDX: "EDX",
- EBX: "EBX",
- ESP: "ESP",
- EBP: "EBP",
- ESI: "ESI",
- EDI: "EDI",
- R8L: "R8L",
- R9L: "R9L",
- R10L: "R10L",
- R11L: "R11L",
- R12L: "R12L",
- R13L: "R13L",
- R14L: "R14L",
- R15L: "R15L",
- RAX: "RAX",
- RCX: "RCX",
- RDX: "RDX",
- RBX: "RBX",
- RSP: "RSP",
- RBP: "RBP",
- RSI: "RSI",
- RDI: "RDI",
- R8: "R8",
- R9: "R9",
- R10: "R10",
- R11: "R11",
- R12: "R12",
- R13: "R13",
- R14: "R14",
- R15: "R15",
- IP: "IP",
- EIP: "EIP",
- RIP: "RIP",
- F0: "F0",
- F1: "F1",
- F2: "F2",
- F3: "F3",
- F4: "F4",
- F5: "F5",
- F6: "F6",
- F7: "F7",
- M0: "M0",
- M1: "M1",
- M2: "M2",
- M3: "M3",
- M4: "M4",
- M5: "M5",
- M6: "M6",
- M7: "M7",
- X0: "X0",
- X1: "X1",
- X2: "X2",
- X3: "X3",
- X4: "X4",
- X5: "X5",
- X6: "X6",
- X7: "X7",
- X8: "X8",
- X9: "X9",
- X10: "X10",
- X11: "X11",
- X12: "X12",
- X13: "X13",
- X14: "X14",
- X15: "X15",
- CS: "CS",
- SS: "SS",
- DS: "DS",
- ES: "ES",
- FS: "FS",
- GS: "GS",
- GDTR: "GDTR",
- IDTR: "IDTR",
- LDTR: "LDTR",
- MSW: "MSW",
- TASK: "TASK",
- CR0: "CR0",
- CR1: "CR1",
- CR2: "CR2",
- CR3: "CR3",
- CR4: "CR4",
- CR5: "CR5",
- CR6: "CR6",
- CR7: "CR7",
- CR8: "CR8",
- CR9: "CR9",
- CR10: "CR10",
- CR11: "CR11",
- CR12: "CR12",
- CR13: "CR13",
- CR14: "CR14",
- CR15: "CR15",
- DR0: "DR0",
- DR1: "DR1",
- DR2: "DR2",
- DR3: "DR3",
- DR4: "DR4",
- DR5: "DR5",
- DR6: "DR6",
- DR7: "DR7",
- DR8: "DR8",
- DR9: "DR9",
- DR10: "DR10",
- DR11: "DR11",
- DR12: "DR12",
- DR13: "DR13",
- DR14: "DR14",
- DR15: "DR15",
- TR0: "TR0",
- TR1: "TR1",
- TR2: "TR2",
- TR3: "TR3",
- TR4: "TR4",
- TR5: "TR5",
- TR6: "TR6",
- TR7: "TR7",
- }
|