#!/usr/bin/perl -w use strict; ### Identify the instruction sets used in a binary file. ### ## Maintainer: Ryan Hill (dirtyepic@gentoo.org) # https://github.com/dirtyepic/scripts/blob/master/analyze-x86 ## Thanks to: # Tavis Ormandy (taviso@cmpxchg8b.com) (original author?) # Will Woods (wwoods@gentoo.org) (improvements) # Georgi Georgiev (chutz@gg3.net) (perl conversion) # Ward Poelmans (wpoely86@gmail.com) (opcode updates) # initialize everything to zero. my ($mmx,$sse,$sse2,$sse3,$ssse3,$sse41,$sse42,$sse4a,$e3dn,$avx,$fma,$fma4,$cpuid) = (0,0,0,0,0,0,0,0,0,0,0,0,0); my $param = $ARGV[0]; # quick sanity tests. defined $param or die "Usage: $0 /path/to/binary\n"; -e $param or die "error: $param does not exist.\n"; -r $param or die "error: cant read $param.\n"; printf "Disassembling %s, please wait...\n\n", $param; # do the disassembling. open PIPE, "objdump -d $param | cut -f3 | cut -d' ' -f1 |" or die; while (defined (my $instruction = )) { chomp $instruction; # MMX if (grep /^$instruction$/, "emms","maskmovq","movq","movntq","packssdw","packsswb","packuswb","paddb","paddd","paddsb","paddsw","paddusb","paddusw","paddw","pand","pandn","pavgusb","pavgb","pavgw","pcmpeqb","pcmpeqd","pcmpeqw","pcmpgtb","pcmpgtd","pcmpgtw","pextrw","pinsrw","pmaddwd","pmaxsw","pmaxub","pminsw","pminub","pmovmskb","pmulhw","pmullw","pmulhuw","por","psadbw","pshufw","pslld","psllq","psllw","psrad","psraw","psrld","psrlq","psrlw","psubb","psubd","psubsb","psubsw","psubusb","psubusw","psubw","punpckhbw","punpckhdq","punpckhwd","punpcklbw","punpckldq","punpcklwd","pxor") { $mmx++ } # SSE elsif (grep /^$instruction$/, "addps","addss","andnps","andps","cmpeqps","cmpeqss","cmpleps","cmpless","cmpltps","cmpltss","cmpneqps","cmpneqss","cmpnleps","cmpnless","cmpnltps","cmpnltss","cmpordps","cmpordss","cmpps","cmpss","cmpunordps","cmpunordss","comiss","cvtpi2ps","cvtps2pi","cvtsi2ss","cvtss2si","cvttps2pi","cvttss2si","divps","divss","ldmxcsr","maxps","maxss","minps","minss","movaps","movhlps","movhps","movlhps","movlps","movmskps","movntps","movss","movups","mulps","mulss","orps","rcpps","rcpss","rsqrtps","rsqrtss","shufps","sqrtps","sqrtss","stmxcsr","subps","subss","ucomiss","unpckhps","unpcklps","xorps") { $sse++ } # Enhanced 3DNow! elsif (grep /^$instruction$/, "pf2iw","pfnacc","pfpnacc","pi2fw","pswapd") { $e3dn++ } # SSE2 elsif (grep /^$instruction$/,"addpd","addsd","andnpd","andpd","clflush","cmpeqpd","cmpeqsd","cmplepd","cmplesd","cmpltpd","cmpltsd","cmpneqpd","cmpneqsd","cmpnlepd","cmpnlesd","cmpnltpd","cmpnltsd","cmpordpd","cmpordsd","cmppd","cmpunordpd","cmpunordsd","comisd","cvtdq2pd","cvtdq2ps","cvtpd2dq","cvtpd2pi","cvtpd2ps","cvtpi2pd","cvtps2dq","cvtps2pd","cvtsd2si","cvtsd2ss","cvtsi2sd","cvtss2sd","cvttpd2dq","cvttpd2pi","cvttps2dq","cvttsd2si","divpd","divsd","maskmovdqu","maxpd","maxsd","minpd","minsd","movapd","movdq2q","movdqa","movdqu","movhpd","movlpd","movmskpd","movntdq","movnti","movntpd","movq2dq","movupd","mulpd","mulsd","orpd","paddq","pmuludq","pshufd","pshufhw","pshuflw","pslldq","psrldq","psubq","punpckhqdq","punpcklqdq","shufpd","sqrtpd","sqrtsd","subpd","subsd","ucomisd","unpckhpd","unpcklpd","xorpd","movd") { $sse2++ } # SSE3 elsif (grep /^$instruction$/, "addsubpd","addsubps","fisttp","haddpd","haddps","hsubpd","hsubps","lddqu","monitor","movddup","movshdup","movsldup","mwait") { $sse3++ } # SSSE3 elsif (grep /^$instruction$/, "pabsb","pabsd","pabsw","palignr","phaddd","phaddsw","phaddw","phsubd","phsubsw","phsubw","pmaddubsw","pmulhrsw","pshufb","psignb","psignd","psignw") { $ssse3++ } # SSE4.1 elsif (grep /^$instruction$/, "blendpd","blendps","blendvpd","blendvps","dppd","dpps","extractps","insertps","movntdqa","mpsadbw","packusdw","pblendvb","pblendw","pcmpeqq","pextrb","pextrd","pextrq","phminposuw","pinsrb","pinsrd","pinsrq","pmaxsb","pmaxsd","pmaxud","pmaxuw","pminsb","pminsd","pminud","pminuw","pmovsxbd","pmovsxbq","pmovsxbw","pmovsxdq","pmovsxwd","pmovsxwq","pmovzxbd","pmovzxbq","pmovzxbw","pmovzxdq","pmovzxwd","pmovzxwq","pmuldq","pmulld","ptest","roundpd","roundps","roundsd","roundss") { $sse41++ } # SSE4.2 elsif (grep /^$instruction$/, "crc32","pcmpestri","pcmpestrm","pcmpgtq","pcmpistri","pcmpistrm","popcnt") { $sse42++ } # SSE4a elsif (grep /^$instruction$/, "extrq", "insertq", "movntsd" ,"movntss") { $sse4a++ } # AVX elsif (grep /^$instruction$/, "pclmulhqhqdq","pclmulhqlqdq","pclmullqhqdq","pclmullqlqdq","pclmulqdq","vaddpd","vaddps","vaddsd","vaddss","vaddsubpd","vaddsubps","vaesdec","vaesdeclast","vaesenc","vaesenclast","vaesimc","vaeskeygenassist","vandnpd","vandnps","vandpd","vandps","vblendpd","vblendps","vblendvpd","vblendvps","vbroadcastf128","vbroadcastsd","vbroadcastss","vcmpeq_ospd","vcmpeq_osps","vcmpeq_ossd","vcmpeq_osss","vcmpeqpd","vcmpeqps","vcmpeqsd","vcmpeqss","vcmpeq_uqpd","vcmpeq_uqps","vcmpeq_uqsd","vcmpeq_uqss","vcmpeq_uspd","vcmpeq_usps","vcmpeq_ussd","vcmpeq_usss","vcmpfalse_oqpd","vcmpfalse_oqps","vcmpfalse_oqsd","vcmpfalse_oqss","vcmpfalse_ospd","vcmpfalse_osps","vcmpfalse_ossd","vcmpfalse_osss","vcmpfalsepd","vcmpfalseps","vcmpfalsesd","vcmpfalsess","vcmpge_oqpd","vcmpge_oqps","vcmpge_oqsd","vcmpge_oqss","vcmpge_ospd","vcmpge_osps","vcmpge_ossd","vcmpge_osss","vcmpgepd","vcmpgeps","vcmpgesd","vcmpgess","vcmpgt_oqpd","vcmpgt_oqps","vcmpgt_oqsd","vcmpgt_oqss","vcmpgt_ospd","vcmpgt_osps","vcmpgt_ossd","vcmpgt_osss","vcmpgtpd","vcmpgtps","vcmpgtsd","vcmpgtss","vcmple_oqpd","vcmple_oqps","vcmple_oqsd","vcmple_oqss","vcmple_ospd","vcmple_osps","vcmple_ossd","vcmple_osss","vcmplepd","vcmpleps","vcmplesd","vcmpless","vcmplt_oqpd","vcmplt_oqps","vcmplt_oqsd","vcmplt_oqss","vcmplt_ospd","vcmplt_osps","vcmplt_ossd","vcmplt_osss","vcmpltpd","vcmpltps","vcmpltsd","vcmpltss","vcmpneq_oqpd","vcmpneq_oqps","vcmpneq_oqsd","vcmpneq_oqss","vcmpneq_ospd","vcmpneq_osps","vcmpneq_ossd","vcmpneq_osss","vcmpneqpd","vcmpneqps","vcmpneqsd","vcmpneqss","vcmpneq_uqpd","vcmpneq_uqps","vcmpneq_uqsd","vcmpneq_uqss","vcmpneq_uspd","vcmpneq_usps","vcmpneq_ussd","vcmpneq_usss","vcmpngepd","vcmpngeps","vcmpngesd","vcmpngess","vcmpnge_uqpd","vcmpnge_uqps","vcmpnge_uqsd","vcmpnge_uqss","vcmpnge_uspd","vcmpnge_usps","vcmpnge_ussd","vcmpnge_usss","vcmpngtpd","vcmpngtps","vcmpngtsd","vcmpngtss","vcmpngt_uqpd","vcmpngt_uqps","vcmpngt_uqsd","vcmpngt_uqss","vcmpngt_uspd","vcmpngt_usps","vcmpngt_ussd","vcmpngt_usss","vcmpnlepd","vcmpnleps","vcmpnlesd","vcmpnless","vcmpnle_uqpd","vcmpnle_uqps","vcmpnle_uqsd","vcmpnle_uqss","vcmpnle_uspd","vcmpnle_usps","vcmpnle_ussd","vcmpnle_usss","vcmpnltpd","vcmpnltps","vcmpnltsd","vcmpnltss","vcmpnlt_uqpd","vcmpnlt_uqps","vcmpnlt_uqsd","vcmpnlt_uqss","vcmpnlt_uspd","vcmpnlt_usps","vcmpnlt_ussd","vcmpnlt_usss","vcmpordpd","vcmpordps","vcmpord_qpd","vcmpord_qps","vcmpord_qsd","vcmpord_qss","vcmpordsd","vcmpord_spd","vcmpord_sps","vcmpordss","vcmpord_ssd","vcmpord_sss","vcmppd","vcmpps","vcmpsd","vcmpss","vcmptruepd","vcmptrueps","vcmptruesd","vcmptruess","vcmptrue_uqpd","vcmptrue_uqps","vcmptrue_uqsd","vcmptrue_uqss","vcmptrue_uspd","vcmptrue_usps","vcmptrue_ussd","vcmptrue_usss","vcmpunordpd","vcmpunordps","vcmpunord_qpd","vcmpunord_qps","vcmpunord_qsd","vcmpunord_qss","vcmpunordsd","vcmpunord_spd","vcmpunord_sps","vcmpunordss","vcmpunord_ssd","vcmpunord_sss","vcomisd","vcomiss","vcvtdq2pd","vcvtdq2ps","vcvtpd2dq","vcvtpd2ps","vcvtps2dq","vcvtps2pd","vcvtsd2si","vcvtsd2ss","vcvtsi2sd","vcvtsi2ss","vcvtss2sd","vcvtss2si","vcvttpd2dq","vcvttps2dq","vcvttsd2si","vcvttss2si","vdivpd","vdivps","vdivsd","vdivss","vdppd","vdpps","vextractf128","vextractps","vhaddpd","vhaddps","vhsubpd","vhsubps","vinsertf128","vinsertps","vlddqu","vldmxcsr","vldqqu","vmaskmovdqu","vmaskmovpd","vmaskmovps","vmaxpd","vmaxps","vmaxsd","vmaxss","vminpd","vminps","vminsd","vminss","vmovapd","vmovaps","vmovd","vmovddup","vmovdqa","vmovdqu","vmovhlps","vmovhpd","vmovhps","vmovlhps","vmovlpd","vmovlps","vmovmskpd","vmovmskps","vmovntdq","vmovntdqa","vmovntpd","vmovntps","vmovntqq","vmovq","vmovqqa","vmovqqu","vmovsd","vmovshdup","vmovsldup","vmovss","vmovupd","vmovups","vmpsadbw","vmulpd","vmulps","vmulsd","vmulss","vorpd","vorps","vpabsb","vpabsd","vpabsw","vpackssdw","vpacksswb","vpackusdw","vpackuswb","vpaddb","vpaddd","vpaddq","vpaddsb","vpaddsw","vpaddusb","vpaddusw","vpaddw","vpalignr","vpand","vpandn","vpavgb","vpavgw","vpblendvb","vpblendw","vpclmulhqhqdq","vpclmulhqlqdq","vpclmullqhqdq","vpclmullqlqdq","vpclmulqdq","vpcmpeqb","vpcmpeqd","vpcmpeqq","vpcmpeqw","vpcmpestri","vpcmpestrm","vpcmpgtb","vpcmpgtd","vpcmpgtq","vpcmpgtw","vpcmpistri","vpcmpistrm","vperm2f128","vpermilpd","vpermilps","vpextrb","vpextrd","vpextrq","vpextrw","vphaddd","vphaddsw","vphaddw","vphminposuw","vphsubd","vphsubsw","vphsubw","vpinsrb","vpinsrd","vpinsrq","vpinsrw","vpmaddubsw","vpmaddwd","vpmaxsb","vpmaxsd","vpmaxsw","vpmaxub","vpmaxud","vpmaxuw","vpminsb","vpminsd","vpminsw","vpminub","vpminud","vpminuw","vpmovmskb","vpmovsxbd","vpmovsxbq","vpmovsxbw","vpmovsxdq","vpmovsxwd","vpmovsxwq","vpmovzxbd","vpmovzxbq","vpmovzxbw","vpmovzxdq","vpmovzxwd","vpmovzxwq","vpmuldq","vpmulhrsw","vpmulhuw","vpmulhw","vpmulld","vpmullw","vpmuludq","vpor","vpsadbw","vpshufb","vpshufd","vpshufhw","vpshuflw","vpsignb","vpsignd","vpsignw","vpslld","vpslldq","vpsllq","vpsllw","vpsrad","vpsraw","vpsrld","vpsrldq","vpsrlq","vpsrlw","vpsubb","vpsubd","vpsubq","vpsubsb","vpsubsw","vpsubusb","vpsubusw","vpsubw","vptest","vpunpckhbw","vpunpckhdq","vpunpckhqdq","vpunpckhwd","vpunpcklbw","vpunpckldq","vpunpcklqdq","vpunpcklwd","vpxor","vrcpps","vrcpss","vroundpd","vroundps","vroundsd","vroundss","vrsqrtps","vrsqrtss","vshufpd","vshufps","vsqrtpd","vsqrtps","vsqrtsd","vsqrtss","vstmxcsr","vsubpd","vsubps","vsubsd","vsubss","vtestpd","vtestps","vucomisd","vucomiss","vunpckhpd","vunpckhps","vunpcklpd","vunpcklps","vxorpd","vxorps","vzeroall","vzeroupper") { $avx++ } # FMA elsif (grep /^$instruction$/, "vfmadd123pd","vfmadd123ps","vfmadd123sd","vfmadd123ss","vfmadd132pd","vfmadd132ps","vfmadd132sd","vfmadd132ss","vfmadd213pd","vfmadd213ps","vfmadd213sd","vfmadd213ss","vfmadd231pd","vfmadd231ps","vfmadd231sd","vfmadd231ss","vfmadd312pd","vfmadd312ps","vfmadd312sd","vfmadd312ss","vfmadd321pd","vfmadd321ps","vfmadd321sd","vfmadd321ss","vfmaddsub123pd","vfmaddsub123ps","vfmaddsub132pd","vfmaddsub132ps","vfmaddsub213pd","vfmaddsub213ps","vfmaddsub231pd","vfmaddsub231ps","vfmaddsub312pd","vfmaddsub312ps","vfmaddsub321pd","vfmaddsub321ps","vfmsub123pd","vfmsub123ps","vfmsub123sd","vfmsub123ss","vfmsub132pd","vfmsub132ps","vfmsub132sd","vfmsub132ss","vfmsub213pd","vfmsub213ps","vfmsub213sd","vfmsub213ss","vfmsub231pd","vfmsub231ps","vfmsub231sd","vfmsub231ss","vfmsub312pd","vfmsub312ps","vfmsub312sd","vfmsub312ss","vfmsub321pd","vfmsub321ps","vfmsub321sd","vfmsub321ss","vfmsubadd123pd","vfmsubadd123ps","vfmsubadd132pd","vfmsubadd132ps","vfmsubadd213pd","vfmsubadd213ps","vfmsubadd231pd","vfmsubadd231ps","vfmsubadd312pd","vfmsubadd312ps","vfmsubadd321pd","vfmsubadd321ps","vfnmadd123pd","vfnmadd123ps","vfnmadd123sd","vfnmadd123ss","vfnmadd132pd","vfnmadd132ps","vfnmadd132sd","vfnmadd132ss","vfnmadd213pd","vfnmadd213ps","vfnmadd213sd","vfnmadd213ss","vfnmadd231pd","vfnmadd231ps","vfnmadd231sd","vfnmadd231ss","vfnmadd312pd","vfnmadd312ps","vfnmadd312sd","vfnmadd312ss","vfnmadd321pd","vfnmadd321ps","vfnmadd321sd","vfnmadd321ss","vfnmsub123pd","vfnmsub123ps","vfnmsub123sd","vfnmsub123ss","vfnmsub132pd","vfnmsub132ps","vfnmsub132sd","vfnmsub132ss","vfnmsub213pd","vfnmsub213ps","vfnmsub213sd","vfnmsub213ss","vfnmsub231pd","vfnmsub231ps","vfnmsub231sd","vfnmsub231ss","vfnmsub312pd","vfnmsub312ps","vfnmsub312sd","vfnmsub312ss","vfnmsub321pd","vfnmsub321ps","vfnmsub321sd","vfnmsub321ss") { $fma++ } # FMA4 elsif (grep /^$instruction$/, "vfmaddpd","vfmaddps","vfmaddsd","vfmaddss","vfmaddsubpd","vfmaddsubps","vfmsubaddpd","vfmsubaddps","vfmsubpd","vfmsubps","vfmsubsd","vfmsubss","vfnmaddpd","vfnmaddps","vfnmaddsd","vfnmaddss","vfnmsubpd","vfnmsubps","vfnmsubsd","vfnmsubss","vfrczpd","vfrczps","vfrczsd","vfrczss","vpcmov","vpcomb","vpcomd","vpcomq","vpcomub","vpcomud","vpcomuq","vpcomuw","vpcomw","vphaddbd","vphaddbq","vphaddbw","vphadddq","vphaddubd","vphaddubq","vphaddubw","vphaddudq","vphadduwd","vphadduwq","vphaddwd","vphaddwq","vphsubbw","vphsubdq","vphsubwd","vpmacsdd","vpmacsdqh","vpmacsdql","vpmacssdd","vpmacssdqh","vpmacssdql","vpmacsswd","vpmacssww","vpmacswd","vpmacsww","vpmadcsswd","vpmadcswd","vpperm","vprotb","vprotd","vprotq","vprotw","vpshab","vpshad","vpshaq","vpshaw","vpshlb","vpshld","vpshlq","vpshlw") { $fma4++ } # CpuID elsif (grep /^$instruction$/, "cpuid") {$cpuid++ } } printf "\tMMX: %13u\n\tSSE: %13u\n\tEnh 3DNow: %7u\n\tSSE2: %12u\n\tSSE3: %12u\n\tSSSE3: %11u\n\tSSE4A: %11u\n\tSSE4.1: %10u\n\tSSE4.2: %10u\n\tAVX: %13u\n\tFMA: %13u\n\tFMA4: %12u\n", $mmx, $sse, $e3dn, $sse2, $sse3, $ssse3, $sse4a, $sse41, $sse42, $avx, $fma, $fma4; # print a newline print "\n"; if ($cpuid) { printf "\nThis binary was found to contain the cpuid instruction.\n"; printf "This could mean that the application checks if an opcode is\n"; printf "supported before executing it, meaning it may work even if\n"; printf "these instructions are not supported on the host.\n\n"; }