golang.org/x/arch@v0.17.0/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 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 `)