1  
     2  
     3  
     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  
    44  
    45  
    46  var objdumpManualTests = `
    47  4883FE017413
    48  488DFC2500000000
    49  488D3D00000000
    50  `
    51  
    52  
    53  
    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  	
    71  	if text == "error: unrecognized instruction" {
    72  		text = "BAD"
    73  	}
    74  
    75  	
    76  	
    77  	
    78  	
    79  	
    80  	if contains(dec.text, "%?", "<internal disassembler error>", "(8087 only)", "(287 only)") {
    81  		dec.text = "(bad)"
    82  	}
    83  
    84  	
    85  	
    86  	
    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  	
    93  	if text == "BAD" && contains(dec.text, "(bad)") {
    94  		return true
    95  	}
    96  
    97  	
    98  	if (text == "BAD" || size == 1 && isPrefix(text)) && hasPrefix(dec.text, unsupported...) {
    99  		return true
   100  	}
   101  
   102  	
   103  	if (contains(dec.text, "(bad)") || dec.nenc == 1 && isPrefix(dec.text)) && hasPrefix(text, libopcodesUnsupported...) {
   104  		return true
   105  	}
   106  
   107  	
   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  	
   113  	
   114  	
   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  	
   124  	
   125  	
   126  	
   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  	
   132  	
   133  	
   134  	if text == "BAD" && contains(dec.text, "nop/reserved") {
   135  		return true
   136  	}
   137  
   138  	
   139  	
   140  	if contains(text, "rdrand") && contains(dec.text, "vmptrld", "vmxon", "vmclear") {
   141  		return true
   142  	}
   143  
   144  	
   145  	
   146  	if text == "BAD" && contains(dec.text, "fnop") && (dec.enc[0] != 0xD9 || dec.enc[1] != 0xD0) {
   147  		return true
   148  	}
   149  
   150  	
   151  	
   152  	
   153  	if contains(text, "nop") && contains(dec.text, "xchg %ax,%ax") {
   154  		return true
   155  	}
   156  
   157  	
   158  	if size == 1 && dec.nenc == 1 && prefixByte[text] > 0 && prefixByte[text] == prefixByte[dec.text] {
   159  		return true
   160  	}
   161  
   162  	
   163  	
   164  	
   165  	if size == 1 && dec.nenc >= 1 && prefixByte[text] == dec.enc[0] && contains(dec.text, "(bad)", "fwait", "fnop") {
   166  		return true
   167  	}
   168  
   169  	
   170  	
   171  	if contains(text, ".+0x2211", ".+0x11") && contains(dec.text, " .-") {
   172  		return true
   173  	}
   174  
   175  	
   176  	
   177  	if countPrefix(inst, 0x66) > 0 && contains(dec.text, "movdq2q", "movq2dq") && !contains(dec.text, "%mm") {
   178  		return true
   179  	}
   180  
   181  	
   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  
   190  
   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  
   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