Home | History | Annotate | Download | only in x86asm
      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
      6 
      7 import (
      8 	"bytes"
      9 	"strings"
     10 	"testing"
     11 )
     12 
     13 func TestObjdump32Manual(t *testing.T)   { testObjdump32(t, hexCases(t, objdumpManualTests)) }
     14 func TestObjdump32Testdata(t *testing.T) { testObjdump32(t, concat(basicPrefixes, testdataCases(t))) }
     15 func TestObjdump32ModRM(t *testing.T)    { testObjdump32(t, concat(basicPrefixes, enumModRM)) }
     16 func TestObjdump32OneByte(t *testing.T)  { testBasic(t, testObjdump32) }
     17 func TestObjdump320F(t *testing.T)       { testBasic(t, testObjdump32, 0x0F) }
     18 func TestObjdump320F38(t *testing.T)     { testBasic(t, testObjdump32, 0x0F, 0x38) }
     19 func TestObjdump320F3A(t *testing.T)     { testBasic(t, testObjdump32, 0x0F, 0x3A) }
     20 func TestObjdump32Prefix(t *testing.T)   { testPrefix(t, testObjdump32) }
     21 
     22 func TestObjdump64Manual(t *testing.T)   { testObjdump64(t, hexCases(t, objdumpManualTests)) }
     23 func TestObjdump64Testdata(t *testing.T) { testObjdump64(t, concat(basicPrefixes, testdataCases(t))) }
     24 func TestObjdump64ModRM(t *testing.T)    { testObjdump64(t, concat(basicPrefixes, enumModRM)) }
     25 func TestObjdump64OneByte(t *testing.T)  { testBasic(t, testObjdump64) }
     26 func TestObjdump640F(t *testing.T)       { testBasic(t, testObjdump64, 0x0F) }
     27 func TestObjdump640F38(t *testing.T)     { testBasic(t, testObjdump64, 0x0F, 0x38) }
     28 func TestObjdump640F3A(t *testing.T)     { testBasic(t, testObjdump64, 0x0F, 0x3A) }
     29 func TestObjdump64Prefix(t *testing.T)   { testPrefix(t, testObjdump64) }
     30 
     31 func TestObjdump64REXTestdata(t *testing.T) {
     32 	testObjdump64(t, filter(concat3(basicPrefixes, rexPrefixes, testdataCases(t)), isValidREX))
     33 }
     34 func TestObjdump64REXModRM(t *testing.T) {
     35 	testObjdump64(t, concat3(basicPrefixes, rexPrefixes, enumModRM))
     36 }
     37 func TestObjdump64REXOneByte(t *testing.T) { testBasicREX(t, testObjdump64) }
     38 func TestObjdump64REX0F(t *testing.T)      { testBasicREX(t, testObjdump64, 0x0F) }
     39 func TestObjdump64REX0F38(t *testing.T)    { testBasicREX(t, testObjdump64, 0x0F, 0x38) }
     40 func TestObjdump64REX0F3A(t *testing.T)    { testBasicREX(t, testObjdump64, 0x0F, 0x3A) }
     41 func TestObjdump64REXPrefix(t *testing.T)  { testPrefixREX(t, testObjdump64) }
     42 
     43 // objdumpManualTests holds test cases that will be run by TestObjdumpManual.
     44 // If you are debugging a few cases that turned up in a longer run, it can be useful
     45 // to list them here and then use -run=ObjdumpManual, particularly with tracing enabled.
     46 var objdumpManualTests = `
     47 4883FE017413
     48 488DFC2500000000
     49 488D3D00000000
     50 `
     51 
     52 // allowedMismatchObjdump reports whether the mismatch between text and dec
     53 // should be allowed by the test.
     54 func allowedMismatchObjdump(text string, size int, inst *Inst, dec ExtInst) bool {
     55 	if size == 15 && dec.nenc == 15 && contains(text, "truncated") && contains(dec.text, "(bad)") {
     56 		return true
     57 	}
     58 
     59 	if i := strings.LastIndex(dec.text, " "); isPrefix(dec.text[i+1:]) && size == 1 && isPrefix(text) {
     60 		return true
     61 	}
     62 
     63 	if size == dec.nenc && contains(dec.text, "movupd") && contains(dec.text, "data32") {
     64 		s := strings.Replace(dec.text, "data32 ", "", -1)
     65 		if text == s {
     66 			return true
     67 		}
     68 	}
     69 
     70 	// Simplify our invalid instruction text.
     71 	if text == "error: unrecognized instruction" {
     72 		text = "BAD"
     73 	}
     74 
     75 	// Invalid instructions for which libopcodes prints %? register.
     76 	// FF E8 11 22 33 44:
     77 	// Invalid instructions for which libopcodes prints "internal disassembler error".
     78 	// Invalid instructions for which libopcodes prints 8087 only (e.g., DB E0)
     79 	// or prints 287 only (e.g., DB E4).
     80 	if contains(dec.text, "%?", "<internal disassembler error>", "(8087 only)", "(287 only)") {
     81 		dec.text = "(bad)"
     82 	}
     83 
     84 	// 0F 19 11, 0F 1C 11, 0F 1D 11, 0F 1E 11, 0F 1F 11: libopcodes says nop,
     85 	// but the Intel manuals say that the only NOP there is 0F 1F /0.
     86 	// Perhaps libopcodes is reporting an older encoding.
     87 	i := bytes.IndexByte(dec.enc[:], 0x0F)
     88 	if contains(dec.text, "nop") && i >= 0 && i+2 < len(dec.enc) && dec.enc[i+1]&^7 == 0x18 && (dec.enc[i+1] != 0x1F || (dec.enc[i+2]>>3)&7 != 0) {
     89 		dec.text = "(bad)"
     90 	}
     91 
     92 	// Any invalid instruction.
     93 	if text == "BAD" && contains(dec.text, "(bad)") {
     94 		return true
     95 	}
     96 
     97 	// Instructions libopcodes knows but we do not (e.g., 0F 19 11).
     98 	if (text == "BAD" || size == 1 && isPrefix(text)) && hasPrefix(dec.text, unsupported...) {
     99 		return true
    100 	}
    101 
    102 	// Instructions we know but libopcodes does not (e.g., 0F D0 11).
    103 	if (contains(dec.text, "(bad)") || dec.nenc == 1 && isPrefix(dec.text)) && hasPrefix(text, libopcodesUnsupported...) {
    104 		return true
    105 	}
    106 
    107 	// Libopcodes rejects F2 90 as NOP. Not sure why.
    108 	if (contains(dec.text, "(bad)") || dec.nenc == 1 && isPrefix(dec.text)) && inst.Opcode>>24 == 0x90 && countPrefix(inst, 0xF2) > 0 {
    109 		return true
    110 	}
    111 
    112 	// 0F 20 11, 0F 21 11, 0F 22 11, 0F 23 11, 0F 24 11:
    113 	// Moves into and out of some control registers seem to be unsupported by libopcodes.
    114 	// TODO(rsc): Are they invalid somehow?
    115 	if (contains(dec.text, "(bad)") || dec.nenc == 1 && isPrefix(dec.text)) && contains(text, "%cr", "%db", "%tr") {
    116 		return true
    117 	}
    118 
    119 	if contains(dec.text, "fwait") && dec.nenc == 1 && dec.enc[0] != 0x9B {
    120 		return true
    121 	}
    122 
    123 	// 9B D9 11: libopcodes reports FSTSW instead of FWAIT + FNSTSW.
    124 	// This is correct in that FSTSW is a pseudo-op for the pair, but it really
    125 	// is a pair of instructions: execution can stop between them.
    126 	// Our decoder chooses to separate them.
    127 	if (text == "fwait" || strings.HasSuffix(text, " fwait")) && dec.nenc >= len(strings.Fields(text)) && dec.enc[len(strings.Fields(text))-1] == 0x9B {
    128 		return true
    129 	}
    130 
    131 	// 0F 18 77 11:
    132 	// Invalid instructions for which libopcodes prints "nop/reserved".
    133 	// Perhaps libopcodes is reporting an older encoding.
    134 	if text == "BAD" && contains(dec.text, "nop/reserved") {
    135 		return true
    136 	}
    137 
    138 	// 0F C7 B0 11 22 33 44: libopcodes says vmptrld 0x44332211(%eax); we say rdrand %eax.
    139 	// TODO(rsc): Fix, since we are probably wrong, but we don't have vmptrld in the manual.
    140 	if contains(text, "rdrand") && contains(dec.text, "vmptrld", "vmxon", "vmclear") {
    141 		return true
    142 	}
    143 
    144 	// DD C8: libopcodes says FNOP but the Intel manual is clear FNOP is only D9 D0.
    145 	// Perhaps libopcodes is reporting an older encoding.
    146 	if text == "BAD" && contains(dec.text, "fnop") && (dec.enc[0] != 0xD9 || dec.enc[1] != 0xD0) {
    147 		return true
    148 	}
    149 
    150 	// 66 90: libopcodes says xchg %ax,%ax; we say 'data16 nop'.
    151 	// The 16-bit swap will preserve the high bits of the register,
    152 	// so they are the same.
    153 	if contains(text, "nop") && contains(dec.text, "xchg %ax,%ax") {
    154 		return true
    155 	}
    156 
    157 	// If there are multiple prefixes, allow libopcodes to use an alternate name.
    158 	if size == 1 && dec.nenc == 1 && prefixByte[text] > 0 && prefixByte[text] == prefixByte[dec.text] {
    159 		return true
    160 	}
    161 
    162 	// 26 9B: libopcodes reports "fwait"/1, ignoring segment prefix.
    163 	// https://sourceware.org/bugzilla/show_bug.cgi?id=16891
    164 	// F0 82: Decode="lock"/1 but libopcodes="lock (bad)"/2.
    165 	if size == 1 && dec.nenc >= 1 && prefixByte[text] == dec.enc[0] && contains(dec.text, "(bad)", "fwait", "fnop") {
    166 		return true
    167 	}
    168 
    169 	// libopcodes interprets 660f801122 as taking a rel16 but
    170 	// truncating the address at 16 bits. Not sure what is correct.
    171 	if contains(text, ".+0x2211", ".+0x11") && contains(dec.text, " .-") {
    172 		return true
    173 	}
    174 
    175 	// 66 F3 0F D6 C5, 66 F2 0F D6 C0: libopcodes reports use of XMM register instead of MMX register,
    176 	// but only when the instruction has a 66 prefix. Maybe they know something we don't.
    177 	if countPrefix(inst, 0x66) > 0 && contains(dec.text, "movdq2q", "movq2dq") && !contains(dec.text, "%mm") {
    178 		return true
    179 	}
    180 
    181 	// 0F 01 F8, 0F 05, 0F 07: these are 64-bit instructions but libopcodes accepts them.
    182 	if (text == "BAD" || size == 1 && isPrefix(text)) && contains(dec.text, "swapgs", "syscall", "sysret", "rdfsbase", "rdgsbase", "wrfsbase", "wrgsbase") {
    183 		return true
    184 	}
    185 
    186 	return false
    187 }
    188 
    189 // Instructions known to libopcodes (or xed) but not to us.
    190 // Most of these come from supplementary manuals of one form or another.
    191 var unsupported = strings.Fields(`
    192 	bndc
    193 	bndl
    194 	bndm
    195 	bnds
    196 	clac
    197 	clgi
    198 	femms
    199 	fldln
    200 	fldz
    201 	getsec
    202 	invlpga
    203 	kmov
    204 	montmul
    205 	pavg
    206 	pf2i
    207 	pfacc
    208 	pfadd
    209 	pfcmp
    210 	pfmax
    211 	pfmin
    212 	pfmul
    213 	pfna
    214 	pfpnac
    215 	pfrc
    216 	pfrs
    217 	pfsub
    218 	phadd
    219 	phsub
    220 	pi2f
    221 	pmulhr
    222 	prefetch
    223 	pswap
    224 	ptest
    225 	rdseed
    226 	sha1
    227 	sha256
    228 	skinit
    229 	stac
    230 	stgi
    231 	vadd
    232 	vand
    233 	vcmp
    234 	vcomis
    235 	vcvt
    236 	vcvt
    237 	vdiv
    238 	vhadd
    239 	vhsub
    240 	vld
    241 	vmax
    242 	vmcall
    243 	vmfunc
    244 	vmin
    245 	vmlaunch
    246 	vmload
    247 	vmmcall
    248 	vmov
    249 	vmov
    250 	vmov
    251 	vmptrld
    252 	vmptrst
    253 	vmread
    254 	vmresume
    255 	vmrun
    256 	vmsave
    257 	vmul
    258 	vmwrite
    259 	vmxoff
    260 	vor
    261 	vpack
    262 	vpadd
    263 	vpand
    264 	vpavg
    265 	vpcmp
    266 	vpcmp
    267 	vpins
    268 	vpmadd
    269 	vpmax
    270 	vpmin
    271 	vpmul
    272 	vpmul
    273 	vpor
    274 	vpsad
    275 	vpshuf
    276 	vpsll
    277 	vpsra
    278 	vpsrad
    279 	vpsrl
    280 	vpsub
    281 	vpunp
    282 	vpxor
    283 	vrcp
    284 	vrsqrt
    285 	vshuf
    286 	vsqrt
    287 	vsub
    288 	vucomis
    289 	vunp
    290 	vxor
    291 	vzero
    292 	xcrypt
    293 	xsha1
    294 	xsha256
    295 	xstore-rng
    296 	insertq
    297 	extrq
    298 	vmclear
    299 	invvpid
    300 	adox
    301 	vmxon
    302 	invept
    303 	adcx
    304 	vmclear
    305 	prefetchwt1
    306 	enclu
    307 	encls
    308 	salc
    309 	fstpnce
    310 	fdisi8087_nop
    311 	fsetpm287_nop
    312 	feni8087_nop
    313 	syscall
    314 	sysret
    315 `)
    316 
    317 // Instructions known to us but not to libopcodes (at least in binutils 2.24).
    318 var libopcodesUnsupported = strings.Fields(`
    319 	addsubps
    320 	aes
    321 	blend
    322 	cvttpd2dq
    323 	dpp
    324 	extract
    325 	haddps
    326 	hsubps
    327 	insert
    328 	invpcid
    329 	lddqu
    330 	movmsk
    331 	movnt
    332 	movq2dq
    333 	mps
    334 	pack
    335 	pblend
    336 	pclmul
    337 	pcmp
    338 	pext
    339 	phmin
    340 	pins
    341 	pmax
    342 	pmin
    343 	pmov
    344 	pmovmsk
    345 	pmul
    346 	popcnt
    347 	pslld
    348 	psllq
    349 	psllw
    350 	psrad
    351 	psraw
    352 	psrl
    353 	ptest
    354 	punpck
    355 	round
    356 	xrstor
    357 	xsavec
    358 	xsaves
    359 	comis
    360 	ucomis
    361 	movhps
    362 	movntps
    363 	rsqrt
    364 	rcpp
    365 	puncpck
    366 	bsf
    367 	movq2dq
    368 	cvttpd2dq
    369 	movq
    370 	hsubpd
    371 	movdqa
    372 	movhpd
    373 	addsubpd
    374 	movd
    375 	haddpd
    376 	cvtps2dq
    377 	bsr
    378 	cvtdq2ps
    379 	rdrand
    380 	maskmov
    381 	movq2dq
    382 	movlhps
    383 	movbe
    384 	movlpd
    385 `)
    386