...

Source file src/golang.org/x/arch/x86/x86asm/objdump_test.go

Documentation: golang.org/x/arch/x86/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  	getsec
   201  	invlpga
   202  	kmov
   203  	montmul
   204  	pavg
   205  	pf2i
   206  	pfacc
   207  	pfadd
   208  	pfcmp
   209  	pfmax
   210  	pfmin
   211  	pfmul
   212  	pfna
   213  	pfpnac
   214  	pfrc
   215  	pfrs
   216  	pfsub
   217  	phadd
   218  	phsub
   219  	pi2f
   220  	pmulhr
   221  	prefetch
   222  	pswap
   223  	ptest
   224  	rdseed
   225  	sha1
   226  	sha256
   227  	skinit
   228  	stac
   229  	stgi
   230  	vadd
   231  	vand
   232  	vcmp
   233  	vcomis
   234  	vcvt
   235  	vcvt
   236  	vdiv
   237  	vhadd
   238  	vhsub
   239  	vld
   240  	vmax
   241  	vmcall
   242  	vmfunc
   243  	vmin
   244  	vmlaunch
   245  	vmload
   246  	vmmcall
   247  	vmov
   248  	vmov
   249  	vmov
   250  	vmptrld
   251  	vmptrst
   252  	vmread
   253  	vmresume
   254  	vmrun
   255  	vmsave
   256  	vmul
   257  	vmwrite
   258  	vmxoff
   259  	vor
   260  	vpack
   261  	vpadd
   262  	vpand
   263  	vpavg
   264  	vpcmp
   265  	vpcmp
   266  	vpins
   267  	vpmadd
   268  	vpmax
   269  	vpmin
   270  	vpmul
   271  	vpmul
   272  	vpor
   273  	vpsad
   274  	vpshuf
   275  	vpsll
   276  	vpsra
   277  	vpsrad
   278  	vpsrl
   279  	vpsub
   280  	vpunp
   281  	vpxor
   282  	vrcp
   283  	vrsqrt
   284  	vshuf
   285  	vsqrt
   286  	vsub
   287  	vucomis
   288  	vunp
   289  	vxor
   290  	vzero
   291  	xcrypt
   292  	xsha1
   293  	xsha256
   294  	xstore-rng
   295  	insertq
   296  	extrq
   297  	vmclear
   298  	invvpid
   299  	adox
   300  	vmxon
   301  	invept
   302  	adcx
   303  	vmclear
   304  	prefetchwt1
   305  	enclu
   306  	encls
   307  	salc
   308  	fstpnce
   309  	fdisi8087_nop
   310  	fsetpm287_nop
   311  	feni8087_nop
   312  	syscall
   313  	sysret
   314  `)
   315  
   316  // Instructions known to us but not to libopcodes (at least in binutils 2.24).
   317  var libopcodesUnsupported = strings.Fields(`
   318  	addsubps
   319  	aes
   320  	blend
   321  	cvttpd2dq
   322  	dpp
   323  	extract
   324  	haddps
   325  	hsubps
   326  	insert
   327  	invpcid
   328  	lddqu
   329  	movmsk
   330  	movnt
   331  	movq2dq
   332  	mps
   333  	pack
   334  	pblend
   335  	pclmul
   336  	pcmp
   337  	pext
   338  	phmin
   339  	pins
   340  	pmax
   341  	pmin
   342  	pmov
   343  	pmovmsk
   344  	pmul
   345  	popcnt
   346  	pslld
   347  	psllq
   348  	psllw
   349  	psrad
   350  	psraw
   351  	psrl
   352  	ptest
   353  	punpck
   354  	round
   355  	xrstor
   356  	xsavec
   357  	xsaves
   358  	comis
   359  	ucomis
   360  	movhps
   361  	movntps
   362  	rsqrt
   363  	rcpp
   364  	puncpck
   365  	bsf
   366  	movq2dq
   367  	cvttpd2dq
   368  	movq
   369  	hsubpd
   370  	movdqa
   371  	movhpd
   372  	addsubpd
   373  	movd
   374  	haddpd
   375  	cvtps2dq
   376  	bsr
   377  	cvtdq2ps
   378  	rdrand
   379  	maskmov
   380  	movq2dq
   381  	movlhps
   382  	movbe
   383  	movlpd
   384  `)
   385  

View as plain text