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