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