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