LEFT | RIGHT |
(no file at all) | |
1 // Copyright 2014 The Go Authors. All rights reserved. | 1 // Copyright 2014 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 // Table-driven decoding of x86 instructions. | 5 // Table-driven decoding of x86 instructions. |
6 | 6 |
7 package x86asm | 7 package x86asm |
8 | 8 |
9 import ( | 9 import ( |
10 "encoding/binary" | 10 "encoding/binary" |
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
162 xArgXmmM32 // arg xmm/m32 | 162 xArgXmmM32 // arg xmm/m32 |
163 xArgXmmM64 // arg xmm/m64 | 163 xArgXmmM64 // arg xmm/m64 |
164 xArgRmf16 // arg r/m16 but force mod=3 | 164 xArgRmf16 // arg r/m16 but force mod=3 |
165 xArgRmf32 // arg r/m32 but force mod=3 | 165 xArgRmf32 // arg r/m32 but force mod=3 |
166 xArgRmf64 // arg r/m64 but force mod=3 | 166 xArgRmf64 // arg r/m64 but force mod=3 |
167 ) | 167 ) |
168 | 168 |
169 // instPrefix returns an Inst describing just one prefix byte. | 169 // instPrefix returns an Inst describing just one prefix byte. |
170 // It is only used if there is a prefix followed by an unintelligible | 170 // It is only used if there is a prefix followed by an unintelligible |
171 // or invalid instruction byte sequence. | 171 // or invalid instruction byte sequence. |
172 func instPrefix(b byte, mode int) (Inst, int, error) { | 172 func instPrefix(b byte, mode int) (Inst, error) { |
173 // When tracing it is useful to see what called instPrefix to report an
error. | 173 // When tracing it is useful to see what called instPrefix to report an
error. |
174 if trace { | 174 if trace { |
175 _, file, line, _ := runtime.Caller(1) | 175 _, file, line, _ := runtime.Caller(1) |
176 fmt.Printf("%s:%d\n", file, line) | 176 fmt.Printf("%s:%d\n", file, line) |
177 } | 177 } |
178 p := Prefix(b) | 178 p := Prefix(b) |
179 switch p { | 179 switch p { |
180 case PrefixDataSize: | 180 case PrefixDataSize: |
181 if mode == 16 { | 181 if mode == 16 { |
182 p = PrefixData32 | 182 p = PrefixData32 |
183 } else { | 183 } else { |
184 p = PrefixData16 | 184 p = PrefixData16 |
185 } | 185 } |
186 case PrefixAddrSize: | 186 case PrefixAddrSize: |
187 if mode == 32 { | 187 if mode == 32 { |
188 p = PrefixAddr16 | 188 p = PrefixAddr16 |
189 } else { | 189 } else { |
190 p = PrefixAddr32 | 190 p = PrefixAddr32 |
191 } | 191 } |
192 } | 192 } |
193 » // Note: using composite literal here confuses 'bundle' tool. | 193 » // Note: using composite literal with Prefix key confuses 'bundle' tool. |
194 » inst := Inst{} | 194 » inst := Inst{Len: 1} |
195 inst.Prefix = Prefixes{p} | 195 inst.Prefix = Prefixes{p} |
196 » return inst, 1, nil | 196 » return inst, nil |
197 } | 197 } |
198 | 198 |
199 // truncated reports a truncated instruction. | 199 // truncated reports a truncated instruction. |
200 // For now we use instPrefix but perhaps later we will return | 200 // For now we use instPrefix but perhaps later we will return |
201 // a specific error here. | 201 // a specific error here. |
202 func truncated(src []byte, mode int) (Inst, int, error) { | 202 func truncated(src []byte, mode int) (Inst, error) { |
203 // return Inst{}, len(src), ErrTruncated | 203 // return Inst{}, len(src), ErrTruncated |
204 return instPrefix(src[0], mode) // too long | 204 return instPrefix(src[0], mode) // too long |
205 } | 205 } |
206 | 206 |
207 // These are the errors returned by Decode. | 207 // These are the errors returned by Decode. |
208 var ( | 208 var ( |
209 ErrInvalidMode = errors.New("invalid x86 mode in Decode") | 209 ErrInvalidMode = errors.New("invalid x86 mode in Decode") |
210 ErrTruncated = errors.New("truncated instruction") | 210 ErrTruncated = errors.New("truncated instruction") |
211 ErrUnrecognized = errors.New("unrecognized instruction") | 211 ErrUnrecognized = errors.New("unrecognized instruction") |
212 ) | 212 ) |
213 | 213 |
214 // decoderCover records coverage information for which parts | 214 // decoderCover records coverage information for which parts |
215 // of the byte code have been executed. | 215 // of the byte code have been executed. |
216 // TODO(rsc): This is for testing. Only use this if a flag is given. | 216 // TODO(rsc): This is for testing. Only use this if a flag is given. |
217 var decoderCover []bool | 217 var decoderCover []bool |
218 | 218 |
219 // Decode decodes the leading bytes in src as a single instruction | 219 // Decode decodes the leading bytes in src as a single instruction. |
220 // returned as inst, along with the number of bytes decoded. | |
221 // The mode arguments specifies the assumed processor mode: | 220 // The mode arguments specifies the assumed processor mode: |
222 // 16, 32, or 64 for 16-, 32-, and 64-bit execution modes. | 221 // 16, 32, or 64 for 16-, 32-, and 64-bit execution modes. |
223 func Decode(src []byte, mode int) (inst Inst, size int, err error) { | 222 func Decode(src []byte, mode int) (inst Inst, err error) { |
224 return decode1(src, mode, false) | 223 return decode1(src, mode, false) |
225 } | 224 } |
226 | 225 |
227 // decode1 is the implementation of Decode but takes an extra | 226 // decode1 is the implementation of Decode but takes an extra |
228 // gnuCompat flag to cause it to change its behavior to mimic | 227 // gnuCompat flag to cause it to change its behavior to mimic |
229 // bugs (or at least unique features) of GNU libopcodes as used | 228 // bugs (or at least unique features) of GNU libopcodes as used |
230 // by objdump. We don't believe that logic is the right thing to do | 229 // by objdump. We don't believe that logic is the right thing to do |
231 // in general, but when testing against libopcodes it simplifies the | 230 // in general, but when testing against libopcodes it simplifies the |
232 // comparison if we adjust a few small pieces of logic. | 231 // comparison if we adjust a few small pieces of logic. |
233 // The affected logic is in the conditional branch for "mandatory" prefixes, | 232 // The affected logic is in the conditional branch for "mandatory" prefixes, |
234 // case xCondPrefix. | 233 // case xCondPrefix. |
235 func decode1(src []byte, mode int, gnuCompat bool) (Inst, int, error) { | 234 func decode1(src []byte, mode int, gnuCompat bool) (Inst, error) { |
236 switch mode { | 235 switch mode { |
237 case 16, 32, 64: | 236 case 16, 32, 64: |
238 // ok | 237 // ok |
239 // TODO(rsc): 64-bit mode not tested, probably not working. | 238 // TODO(rsc): 64-bit mode not tested, probably not working. |
240 default: | 239 default: |
241 » » return Inst{}, 0, ErrInvalidMode | 240 » » return Inst{}, ErrInvalidMode |
242 } | 241 } |
243 | 242 |
244 // Maximum instruction size is 15 bytes. | 243 // Maximum instruction size is 15 bytes. |
245 // If we need to read more, return 'truncated instruction. | 244 // If we need to read more, return 'truncated instruction. |
246 if len(src) > 15 { | 245 if len(src) > 15 { |
247 src = src[:15] | 246 src = src[:15] |
248 } | 247 } |
249 | 248 |
250 var ( | 249 var ( |
251 // prefix decoding information | 250 // prefix decoding information |
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
440 println("run", pc) | 439 println("run", pc) |
441 } | 440 } |
442 x := decoder[pc] | 441 x := decoder[pc] |
443 decoderCover[pc] = true | 442 decoderCover[pc] = true |
444 pc++ | 443 pc++ |
445 | 444 |
446 // Read and decode ModR/M if needed by opcode. | 445 // Read and decode ModR/M if needed by opcode. |
447 switch decodeOp(x) { | 446 switch decodeOp(x) { |
448 case xCondSlashR, xReadSlashR: | 447 case xCondSlashR, xReadSlashR: |
449 if haveModrm { | 448 if haveModrm { |
450 » » » » return inst, pos, errInternal | 449 » » » » return Inst{Len: pos}, errInternal |
451 } | 450 } |
452 haveModrm = true | 451 haveModrm = true |
453 if pos >= len(src) { | 452 if pos >= len(src) { |
454 return truncated(src, mode) | 453 return truncated(src, mode) |
455 } | 454 } |
456 modrm = int(src[pos]) | 455 modrm = int(src[pos]) |
457 pos++ | 456 pos++ |
458 if opshift >= 0 { | 457 if opshift >= 0 { |
459 inst.Opcode |= uint32(modrm) << uint(opshift) | 458 inst.Opcode |= uint32(modrm) << uint(opshift) |
460 opshift -= 8 | 459 opshift -= 8 |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
575 | 574 |
576 if segIndex >= 0 { | 575 if segIndex >= 0 { |
577 mem.Segment = prefixToSegment(inst.Prefix[segInd
ex]) | 576 mem.Segment = prefixToSegment(inst.Prefix[segInd
ex]) |
578 } | 577 } |
579 } | 578 } |
580 | 579 |
581 // Execute single opcode. | 580 // Execute single opcode. |
582 switch decodeOp(x) { | 581 switch decodeOp(x) { |
583 default: | 582 default: |
584 println("bad op", x, "at", pc-1, "from", oldPC) | 583 println("bad op", x, "at", pc-1, "from", oldPC) |
585 » » » return inst, pos, errInternal | 584 » » » return Inst{Len: pos}, errInternal |
586 | 585 |
587 case xFail: | 586 case xFail: |
588 inst.Op = 0 | 587 inst.Op = 0 |
589 break Decode | 588 break Decode |
590 | 589 |
591 case xMatch: | 590 case xMatch: |
592 break Decode | 591 break Decode |
593 | 592 |
594 case xJump: | 593 case xJump: |
595 pc = int(decoder[pc]) | 594 pc = int(decoder[pc]) |
(...skipping 553 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1149 inst.Args[narg] = Rel(int32(immc)) | 1148 inst.Args[narg] = Rel(int32(immc)) |
1150 narg++ | 1149 narg++ |
1151 } | 1150 } |
1152 } | 1151 } |
1153 | 1152 |
1154 if inst.Op == 0 { | 1153 if inst.Op == 0 { |
1155 // Invalid instruction. | 1154 // Invalid instruction. |
1156 if nprefix > 0 { | 1155 if nprefix > 0 { |
1157 return instPrefix(src[0], mode) // invalid instruction | 1156 return instPrefix(src[0], mode) // invalid instruction |
1158 } | 1157 } |
1159 » » return Inst{}, pos, ErrUnrecognized | 1158 » » return Inst{Len: pos}, ErrUnrecognized |
1160 } | 1159 } |
1161 | 1160 |
1162 // Matched! Hooray! | 1161 // Matched! Hooray! |
1163 | 1162 |
1164 // 90 decodes as XCHG EAX, EAX but is NOP. | 1163 // 90 decodes as XCHG EAX, EAX but is NOP. |
1165 // 66 90 decodes as XCHG AX, AX and is NOP too. | 1164 // 66 90 decodes as XCHG AX, AX and is NOP too. |
1166 // 48 90 decodes as XCHG RAX, RAX and is NOP too. | 1165 // 48 90 decodes as XCHG RAX, RAX and is NOP too. |
1167 // 43 90 decodes as XCHG R8D, EAX and is *not* NOP. | 1166 // 43 90 decodes as XCHG R8D, EAX and is *not* NOP. |
1168 // F3 90 decodes as REP XCHG EAX, EAX but is PAUSE. | 1167 // F3 90 decodes as REP XCHG EAX, EAX but is PAUSE. |
1169 // It's all too special to handle in the decoding tables, at least for n
ow. | 1168 // It's all too special to handle in the decoding tables, at least for n
ow. |
(...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1422 rexUsed |= PrefixREX | 1421 rexUsed |= PrefixREX |
1423 } | 1422 } |
1424 if rex&^rexUsed == 0 { | 1423 if rex&^rexUsed == 0 { |
1425 inst.Prefix[rexIndex] |= PrefixImplicit | 1424 inst.Prefix[rexIndex] |= PrefixImplicit |
1426 } | 1425 } |
1427 } | 1426 } |
1428 | 1427 |
1429 inst.DataSize = dataMode | 1428 inst.DataSize = dataMode |
1430 inst.AddrSize = addrMode | 1429 inst.AddrSize = addrMode |
1431 inst.Mode = mode | 1430 inst.Mode = mode |
1432 » return inst, pos, nil | 1431 » inst.Len = pos |
| 1432 » return inst, nil |
1433 } | 1433 } |
1434 | 1434 |
1435 var errInternal = errors.New("internal error") | 1435 var errInternal = errors.New("internal error") |
1436 | 1436 |
1437 // addr16 records the eight 16-bit addressing modes. | 1437 // addr16 records the eight 16-bit addressing modes. |
1438 var addr16 = [8]Mem{ | 1438 var addr16 = [8]Mem{ |
1439 {Base: BX, Scale: 1, Index: SI}, | 1439 {Base: BX, Scale: 1, Index: SI}, |
1440 {Base: BX, Scale: 1, Index: DI}, | 1440 {Base: BX, Scale: 1, Index: DI}, |
1441 {Base: BP, Scale: 1, Index: SI}, | 1441 {Base: BP, Scale: 1, Index: SI}, |
1442 {Base: BP, Scale: 1, Index: DI}, | 1442 {Base: BP, Scale: 1, Index: DI}, |
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1607 } | 1607 } |
1608 | 1608 |
1609 // isLoop records the loop operators. | 1609 // isLoop records the loop operators. |
1610 var isLoop = [maxOp + 1]bool{ | 1610 var isLoop = [maxOp + 1]bool{ |
1611 LOOP: true, | 1611 LOOP: true, |
1612 LOOPE: true, | 1612 LOOPE: true, |
1613 LOOPNE: true, | 1613 LOOPNE: true, |
1614 JECXZ: true, | 1614 JECXZ: true, |
1615 JRCXZ: true, | 1615 JRCXZ: true, |
1616 } | 1616 } |
LEFT | RIGHT |