Cara memeriksa apakah biner memerlukan SSE4 atau AVX di Linux

20

Di Linux, /proc/cpuinfomemungkinkan seseorang untuk memeriksa semua flag CPU yang dimiliki mesin dengan cara yang sederhana.
Biasanya, jika suatu program membutuhkan superset dari set instruksi mesin, cara termudah untuk menentukan ini adalah dengan menjalankannya dan melihat apakah itu menimbulkan SIGILLsinyal.

Tetapi dalam kasus saya, semua prosesor saya mendukung setidaknya SSE4.1 dan AVX.
Jadi, apakah ada cara sederhana untuk memeriksa apakah biner memiliki instruksi khusus di dalamnya?

pengguna2284570
sumber
Mungkin ada emulator yang memungkinkan Anda memilih set instruksi mana yang diaktifkan. QEMU saat ini tidak mendukung AVX, sehingga mungkin "tidak berfungsi" seperti yang diharapkan di sana: superuser.com/questions/453786/how-do-i-get-avx-support-in-qemu || superuser.com/questions/548740/…
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件
2
objdump --disassemblemelakukan pembongkaran. Anda dapat menggunakan objdumpuntuk membuat daftar mnemonik. Ini adalah bagian dari Binutils, jadi tersedia di sistem Linux GNU. Juga, instruksi tambahan mungkin ada tetapi tidak dapat dieksekusi. Program bisa memiliki penjaga runtime.
jww
@jww: heemm, ya tapi saya repot-repot menjalankan executable di mana-mana, bukan tentang belajar lebih dari 600 opcodes untuk memprogram dalam perakitan.
user2284570
Anda harus belajar apa yang bisa (dan tidak bisa) Anda gunakan. Itu tanggung jawabmu. Saya kira Anda bisa mengkompilasi -mavxuntuk memastikan kompiler hanya memilih dari AVX ISA, tetapi ada cara untuk menghindarinya. Sebagai contoh, assembler inline biasanya dapat menghindari pemeriksaan ISA kompiler.
jww
@ jww: dan jika biner adalah sumber tertutup (dalam arti kode sumber dihapus setelah bangunan) objek bersama dibangun oleh skrip / kompiler hak milik?
user2284570

Jawaban:

11

Saya menghentikan program di Rust yang mencoba melakukan ini. Saya pikir itu berhasil, meskipun tidak terdokumentasi dan sangat rapuh:

https://github.com/pkgw/elfx86exts

Contoh penggunaan:

$ cd elfx86exts
$ cargo build
[things happen]
$ cargo run -- /bin/ls
   Compiling elfx86exts v0.1.0 (file:///home/peter/sw/elfx86exts)
    Finished dev [unoptimized + debuginfo] target(s) in 1.9 secs
     Running `target/debug/elfx86exts /bin/ls`
MODE64
CMOV
SSE2
SSE1
Peter
sumber
Saya mencoba menjalankannya di libtensorflow.so (sha224: 8f665acf0f455d5056014dfa2d48c22ab6cf83eb073842e8304878d0) dari paket ini (versi: 1.8.0-5) dan membeku di seluruh komputer saya.
Philippe
@Philippe Silakan ajukan masalah di GitHub! Itu tempat yang lebih baik untuk membahas topik semacam itu, saya pikir.
Peter
Oke, saya membuat masalah di github Anda.
Philippe
18

Saya mengalami masalah yang sama ketika saya mencoba memahami proses optimasi GCC dan untuk mengetahui instruksi mana yang telah atau belum digunakan selama proses ini. Karena saya tidak ramah dengan sejumlah besar kode operasi, saya mencari cara untuk memvisualisasikan instruksi spesifik (misalkan SSE3) dalam kode yang dibongkar, atau setidaknya mencetak beberapa statistik minimal seperti apakah dan berapa banyak instruksi ini yang ada dalam biner.

Saya belum menemukan solusi yang ada, tetapi jawaban Jonathan Ben-Avraham terbukti sangat berguna, karena menunjukkan sumber kode operasi yang hebat (dan bahkan sebagian terstruktur). Berdasarkan data ini, saya telah menulis skrip Bash yang dapat memvisualisasikan set instruksi khusus atau mencetak statistik tentang mereka menggunakan grepketika diumpankan dengan output dari objdump.

Daftar kode operasi telah diubah menjadi skrip Bash mandiri yang kemudian dimasukkan (untuk tujuan keterbacaan yang lebih baik) dalam file utama yang saya beri nama sederhana opcode. Karena opcodes dalam gas.vim( definisi sintaksis Shirkvim , dari jawaban Jonathan) dikelompokkan secara sistematis (tampaknya) menurut arsitektur CPU yang berbeda, saya mencoba mempertahankan divisi ini dan membuat pemetaan kumpulan instruksi arsitektur-> ; Saya tidak yakin sekarang apakah itu ide yang bagus. Pemetaannya tidak akurat dan saya bahkan harus membuat beberapa perubahan pada aslinyagas.vimpengelompokan. Karena set instruksi yang berhubungan dengan arsitektur bukan niat asli saya, saya mencoba hanya untuk membangun set instruksi arsitektur utama yang dijelaskan di Internet, tetapi tanpa berkonsultasi dengan dokumentasi pabrik. Arsitektur AMD sepertinya tidak bisa diandalkan sama sekali bagi saya (kecuali set instruksi seperti 3DNow! Dan SSE5). Namun, saya memutuskan untuk meninggalkan kode untuk set instruksi dari berbagai arsitektur di sini untuk orang lain untuk memeriksa dan memperbaiki / memberikan hasil tentatif kepada orang lain.

Awal dari file utama bernama opcode:

#!/bin/bash
#
# Searches disassembled code for specific instructions.
#
# Opcodes obtained from: https://github.com/Shirk/vim-gas/blob/master/syntax/gas.vim
#
# List of opcodes has been obtained using the following commands and making a few modifications:
#   echo '#!/bin/bash' > Opcode_list
#   wget -q -O- https://raw.githubusercontent.com/Shirk/vim-gas/master/syntax/gas.vim \
#    | grep -B1 -E 'syn keyword gasOpcode_|syn match   gasOpcode' | \
#    sed -e '/^--$/d' -e 's/"-- Section:/\n#/g' \
#    -e 's/syn keyword gasOpcode_\([^\t]*\)*\(\t\)*\(.*\)/Opcode_\1="\${Opcode_\1} \3"/g' \
#    -e 's/Opcode_PENT_3DNOW/Opcode_ATHLON_3DNOW/g' -e 's/\\//g' \
#    -e 's/syn match   gasOpcode_\([^\t]*\)*.*\/<\(.*\)>\//Opcode_\1="\${Opcode_\1} \2"/g' \
#    >> Opcode_list
#
# Modify file Opcode_list replacing all occurrences of:
#   * Opcode_Base within the section "Tejas New Instructions (SSSE3)" with Opcode_SSSE3
#   * Opcode_Base within the section "Willamette MMX instructions (SSE2 SIMD Integer Instructions)"
#                                        with Opcode_WILLAMETTE_Base

# return values
EXIT_FOUND=0
EXIT_NOT_FOUND=1
EXIT_USAGE=2

# settings
InstSet_Base=""
Recursive=false
Count_Matching=false
Leading_Separator='\s'
Trailing_Separator='(\s|$)' # $ matches end of line for non-parametric instructions like nop
Case_Insensitive=false
Invert=false
Verbose=false
Stop_After=0
Line_Numbers=false
Leading_Context=0
Trailing_Context=0

source Opcode_list   # include opcodes from a separate file

# GAS-specific opcodes (unofficial names) belonging to the x64 instruction set.
# They are generated by GNU tools (e.g. GDB, objdump) and specify a variant of ordinal opcodes like NOP and MOV.
# If you do not want these opcodes to be recognized by this script, comment out the following line.
Opcode_X64_GAS="nopw nopl movabs"


# instruction sets
InstSet_X86="8086_Base 186_Base 286_Base 386_Base 486_Base PENT_Base P6_Base KATMAI_Base WILLAMETTE_Base PENTM_Base"
InstSet_IA64="IA64_Base"
InstSet_X64="PRESCOTT_Base X64_Base X86_64_Base NEHALEM_Base X64_GAS"
InstSet_MMX="PENT_MMX KATMAI_MMX X64_MMX"
InstSet_MMX2="KATMAI_MMX2"
InstSet_3DNOW="ATHLON_3DNOW"
InstSet_SSE="KATMAI_SSE P6_SSE X64_SSE"
InstSet_SSE2="SSE2 X64_SSE2"
InstSet_SSE3="PRESCOTT_SSE3"
InstSet_SSSE3="SSSE3"
InstSet_VMX="VMX X64_VMX"
InstSet_SSE4_1="SSE41 X64_SSE41"
InstSet_SSE4_2="SSE42 X64_SSE42"
InstSet_SSE4A="AMD_SSE4A"
InstSet_SSE5="AMD_SSE5"
InstSet_FMA="FUTURE_FMA"
InstSet_AVX="SANDYBRIDGE_AVX"

InstSetDep_X64="X86"
InstSetDep_MMX2="MMX"
InstSetDep_SSE2="SSE"
InstSetDep_SSE3="SSE2"
InstSetDep_SSSE3="SSE3"
InstSetDep_SSE4_1="SSSE3"
InstSetDep_SSE4_2="SSE4_1"
InstSetDep_SSE4A="SSE3"
InstSetDep_SSE5="FMA AVX" # FIXME not reliable

InstSetList="X86 IA64 X64 MMX MMX2 3DNOW SSE SSE2 SSE3 SSSE3 VMX SSE4_1 SSE4_2 SSE4A SSE5 FMA AVX"


# architectures
Arch_8086="8086_Base"
Arch_186="186_Base"
Arch_286="286_Base"
Arch_386="386_Base"
Arch_486="486_Base"
Arch_Pentium="PENT_Base PENT_MMX" # Pentium = P5 architecture
Arch_Athlon="ATHLON_3DNOW"
Arch_Deschutes="P6_Base P6_SSE" # Pentium II
Arch_Katmai="KATMAI_Base KATMAI_MMX KATMAI_MMX2 KATMAI_SSE" # Pentium III
Arch_Willamette="WILLAMETTE_Base SSE2" # original Pentium IV (x86)
Arch_PentiumM="PENTM_Base"
Arch_Prescott="PRESCOTT_Base X64_Base X86_64_Base X64_SSE2 PRESCOTT_SSE3 VMX X64_VMX X64_GAS" # later Pentium IV (x64) with SSE3 (Willamette only implemented SSE2 instructions) and VT (VT-x, aka VMX)
Arch_P6=""
Arch_Barcelona="ATHLON_3DNOW AMD_SSE4A"
Arch_IA64="IA64_Base" # 64-bit Itanium RISC processor; incompatible with x64 architecture
Arch_Penryn="SSSE3 SSE41 X64_SSE41" # later (45nm) Core 2 with SSE4.1
Arch_Nehalem="NEHALEM_Base SSE42 X64_SSE42" # Core i#
Arch_SandyBridge="SANDYBRIDGE_AVX"
Arch_Haswell="FUTURE_FMA"
Arch_Bulldozer="AMD_SSE5"

ArchDep_8086=""
ArchDep_186="8086"
ArchDep_286="186"
ArchDep_386="286"
ArchDep_486="386"
ArchDep_Pentium="486"
ArchDep_Athlon="Pentium" # FIXME not reliable
ArchDep_Deschutes="Pentium"
ArchDep_Katmai="Deschutes"
ArchDep_Willamette="Katmai"
ArchDep_PentiumM="Willamette" # FIXME Pentium M is a Pentium III modification (with SSE2). Does it support also WILLAMETTE_Base instructions?
ArchDep_Prescott="Willamette"
ArchDep_P6="Prescott" # P6 started with Pentium Pro; FIXME Pentium Pro did not support MMX instructions (introduced again in Pentium II aka Deschutes)
ArchDep_Barcelona="Prescott" # FIXME not reliable
ArchDep_IA64=""
ArchDep_Penryn="P6"
ArchDep_Nehalem="Penryn"
ArchDep_SandyBridge="Nehalem"
ArchDep_Haswell="SandyBridge"
ArchDep_Bulldozer="Haswell" # FIXME not reliable

ArchList="8086 186 286 386 486 Pentium Athlon Deschutes Katmai Willamette PentiumM Prescott P6 Barcelona IA64 Penryn Nehalem SandyBridge Haswell Bulldozer"

Contoh Opcode_listfile yang dibuat dan dimodifikasi menggunakan instruksi pada opcode27 Oktober 2014, dapat ditemukan di http://pastebin.com/yx4rCxqs . Anda dapat memasukkan file ini tepat opcodedi tempat source Opcode_listbaris. Saya telah mengeluarkan kode ini karena Stack Exchange tidak akan membiarkan saya mengirim jawaban sebesar itu.

Akhirnya, sisa opcodefile dengan logika aktual:

usage() {
    echo "Usage: $0 OPTIONS"
    echo ""
    echo "  -r      set instruction sets recursively according to dependency tree (must precede -a or -s)"
    echo "  -a      set architecture"
    echo "  -s      set instruction set"
    echo "  -L      show list of available architectures"
    echo "  -l      show list of available instruction sets"
    echo "  -i      show base instruction sets of current instruction set (requires -a and/or -s)"
    echo "  -I      show instructions in current instruction set (requires -a and/or -s)"
    echo "  -c      print number of matching instructions instead of normal output"
    echo "  -f      find instruction set of the following instruction (regex allowed)"
    echo "  -d      set leading opcode separator (default '$Leading_Separator')"
    echo "  -D      set trailing opcode separator (default '$Trailing_Separator')"
    echo "  -C      case-insensitive"
    echo "  -v      invert the sense of matching"
    echo "  -V      print all lines, not just the highlighted"
    echo "  -m      stop searching after n matched instructions"
    echo "  -n      print line numbers within the original input"
    echo "  -B      print n instructions of leading context"
    echo "  -A      print n instructions of trailing context"
    echo "  -h      print this help"
    echo
    echo "Multiple architectures and instruction sets can be used."
    echo
    echo "Typical usage is:"
    echo "  objdump -M intel -d FILE | $0 OPTIONS"
    echo "  objdump -M intel -d FILE | $0 -s SSE2 -s SSE3 -V                    Highlight SSE2 and SSE3 within FILE."
    echo "  objdump -M intel -d FILE | tail -n +8 | $0 -r -a Haswell -v -m 1    Find first unknown instruction."
    echo "  $0 -C -f ADDSD                                                      Find which instruction set an opcode belongs to."
    echo "  $0 -f .*fma.*                                                       Find all matching instructions and their instruction sets."
    echo
    echo "The script uses Intel opcode syntax. When used in conjunction with objdump, \`-M intel' must be set in order to prevent opcode translation using AT&T syntax."
    echo
    echo "BE AWARE THAT THE LIST OF KNOWN INSTRUCTIONS OR INSTRUCTIONS SUPPORTED BY PARTICULAR ARCHITECTURES (ESPECIALLY AMD'S) IS ONLY TENTATIVE AND MAY CONTAIN MISTAKES!"
    kill -TRAP $TOP_PID
}

list_contains() {   # Returns 0 if $2 is in array $1, 1 otherwise.
    local e
    for e in $1; do
        [ "$e" = "$2" ] && return 0
    done
    return 1
}

build_instruction_set() {   # $1 = enum { Arch, InstSet }, $2 = architecture or instruction set as obtained using -L or -l, $3 = "architecture"/"instruction set" to be used in error message
    local e
    list_contains "`eval echo \\\$${1}List`" "$2" || (echo "$2 is not a valid $3."; usage)      # Test if the architecture/instruction set is valid.
    if [ -n "`eval echo \\\$${1}_${2}`" ]; then                                                 # Add the instruction set(s) if any.
        for e in `eval echo \\\$${1}_${2}`; do                                                  # Skip duplicates.
            list_contains "$InstSet_Base" $e || InstSet_Base="$e $InstSet_Base"
        done
    fi
    if [ $Recursive = true ]; then
        for a in `eval echo \\\$${1}Dep_$2`; do
            build_instruction_set $1 $a "$3"
        done
    fi
    InstSet_Base="`echo $InstSet_Base | sed 's/$ *//'`"                                         # Remove trailing space.
}

trap "exit $EXIT_USAGE" TRAP    # Allow usage() function to abort script execution.
export TOP_PID=$$               # PID of executing process.

# Parse command line arguments.
while getopts ":ra:s:LliIcf:Fd:D:CvVm:nB:A:h" o; do
    case $o in
        r) Recursive=true ;;
        a) build_instruction_set Arch "$OPTARG" "architecture" ;;
        s) build_instruction_set InstSet "$OPTARG" "instruction set" ;;
        L) echo $ArchList; exit $EXIT_USAGE ;;
        l) echo $InstSetList; exit $EXIT_USAGE ;;
        i)
            if [ -n "$InstSet_Base" ]; then
                echo $InstSet_Base
                exit $EXIT_USAGE
            else
                echo -e "No instruction set or architecture set.\n"
                usage
            fi
            ;;
        I)
            if [ -n "$InstSet_Base" ]; then
                for s in $InstSet_Base; do
                    echo -ne "\e[31;1m$s:\e[0m "
                    eval echo "\$Opcode_$s"
                done
                exit $EXIT_USAGE
            else
                echo -e "No instruction set or architecture set.\n"
                usage
            fi
            ;;
        c) Count_Matching=true ;;
        f)
            # Unlike architectures, instruction sets are disjoint.
            Found=false
            for s in $InstSetList; do
                for b in `eval echo \\\$InstSet_$s`; do
                    Found_In_Base=false
                    for i in `eval echo \\\$Opcode_$b`; do
                        if [[ "$i" =~ ^$OPTARG$ ]]; then
                            $Found_In_Base || echo -ne "Instruction set \e[33;1m$s\e[0m (base instruction set \e[32;1m$b\e[0m):"
                            echo -ne " \e[31;1m$i\e[0m"
                            Found_In_Base=true
                            Found=true
                        fi
                    done
                    $Found_In_Base && echo ""
                done
            done
            if [ $Found = false ]; then
                echo -e "Operation code \e[31;1m$OPTARG\e[0m has not been found in the database of known instructions." \
                "Perhaps it is translated using other than Intel syntax. If obtained from objdump, check if the \`-M intel' flag is set." \
                "Be aware that the search is case sensitive by default (you may use the -C flag, otherwise only lower case opcodes are accepted)."
                exit $EXIT_NOT_FOUND
            else
                exit $EXIT_FOUND
            fi
            ;;
        d) Leading_Separator="$OPTARG" ;;
        D) Trailing_Separator="$OPTARG" ;;
        C) Case_Insensitive=true ;;
        v) Invert=true ;;
        V) Verbose=true ;;
        m) Stop_After=$OPTARG ;;
        n) Line_Numbers=true ;;
        B) Leading_Context=$OPTARG ;;
        A) Trailing_Context=$OPTARG ;;
        h) usage ;;
        \?)
            echo -e "Unknown option: -$OPTARG\n"
            usage
            ;;
    esac
done
shift $((OPTIND-1))
[ -n "$1" ] && echo -e "Unknown command line parameter: $1\n" && usage
[ -z "$InstSet_Base" ] && usage

# Create list of grep parameters.
Grep_Params="--color=auto -B $Leading_Context -A $Trailing_Context"
[ $Count_Matching = true ] && Grep_Params="$Grep_Params -c"
[ $Case_Insensitive = true ] && Grep_Params="$Grep_Params -i"
[ $Invert = true ] && Grep_Params="$Grep_Params -v"
[ $Stop_After -gt 0 ] && Grep_Params="$Grep_Params -m $Stop_After"
[ $Line_Numbers = true ] && Grep_Params="$Grep_Params -n"

# Build regular expression for use in grep.
RegEx=""
for s in $InstSet_Base; do
    eval RegEx=\"$RegEx \$Opcode_$s\"
done
# Add leading and trailing opcode separators to prevent false positives.
RegEx="$Leading_Separator`echo $RegEx | sed "s/ /$(echo "$Trailing_Separator"|sed 's/[\/&]/\\\&/g')|$(echo "$Leading_Separator"|sed 's/[\/&]/\\\&/g')/g"`$Trailing_Separator"

[ $Verbose = true -a $Count_Matching = false ] && RegEx="$RegEx|\$"

# The actual search.
grep $Grep_Params -E "$RegEx" && exit $EXIT_FOUND || exit $EXIT_NOT_FOUND

Perlu diketahui bahwa jika permintaan pencarian Anda terlalu besar (mis., Dengan set instruksi Haswell dan -rsakelar - ini termasuk ratusan instruksi), perhitungannya dapat berjalan perlahan dan membutuhkan waktu lama pada input besar yang tidak dimaksudkan untuk skrip sederhana ini. .

Untuk informasi rinci tentang penggunaan, konsultasikan

./opcode -h

Seluruh opcodeskrip (dengan menyertakan Opcode_list) dapat ditemukan di http://pastebin.com/A8bAuHAP .

Jangan ragu untuk meningkatkan alat dan untuk memperbaiki kesalahan yang mungkin saya buat. Terakhir, saya ingin mengucapkan terima kasih kepada Jonathan Ben-Avraham atas ide bagusnya menggunakan gas.vimfile Shirk .

EDIT: Script sekarang dapat menemukan instruksi yang mengatur kode operasi milik (ekspresi reguler dapat digunakan).

Kyselejsyreček
sumber
9

Pertama, dekompilasi biner Anda:

objdump -d binary > binary.asm

Kemudian temukan semua instruksi SSE4 di file assembly:

awk '/[ \t](mpsadbw|phminposuw|pmulld|pmuldq|dpps|dppd|blendps|blendpd|blendvps|blendvpd|pblendvb|pblenddw|pminsb|pmaxsb|pminuw|pmaxuw|pminud|pmaxud|pminsd|pmaxsd|roundps|roundss|roundpd|roundsd|insertps|pinsrb|pinsrd|pinsrq|extractps|pextrb|pextrd|pextrw|pextrq|pmovsxbw|pmovzxbw|pmovsxbd|pmovzxbd|pmovsxbq|pmovzxbq|pmovsxwd|pmovzxwd|pmovsxwq|pmovzxwq|pmovsxdq|pmovzxdq|ptest|pcmpeqq|pcmpgtq|packusdw|pcmpestri|pcmpestrm|pcmpistri|pcmpistrm|crc32|popcnt|movntdqa|extrq|insertq|movntsd|movntss|lzcnt)[ \t]/' binary.asm

(Catatan: CRC32 mungkin cocok dengan komentar.)

Temukan instruksi AVX paling umum (termasuk skalar, termasuk AVX2, AVX-512 family dan beberapa sejenis FMA vfmadd132pd):

awk '/[ \t](vmovapd|vmulpd|vaddpd|vsubpd|vfmadd213pd|vfmadd231pd|vfmadd132pd|vmulsd|vaddsd|vmosd|vsubsd|vbroadcastss|vbroadcastsd|vblendpd|vshufpd|vroundpd|vroundsd|vxorpd|vfnmadd231pd|vfnmadd213pd|vfnmadd132pd|vandpd|vmaxpd|vmovmskpd|vcmppd|vpaddd|vbroadcastf128|vinsertf128|vextractf128|vfmsub231pd|vfmsub132pd|vfmsub213pd|vmaskmovps|vmaskmovpd|vpermilps|vpermilpd|vperm2f128|vzeroall|vzeroupper|vpbroadcastb|vpbroadcastw|vpbroadcastd|vpbroadcastq|vbroadcasti128|vinserti128|vextracti128|vpminud|vpmuludq|vgatherdpd|vgatherqpd|vgatherdps|vgatherqps|vpgatherdd|vpgatherdq|vpgatherqd|vpgatherqq|vpmaskmovd|vpmaskmovq|vpermps|vpermd|vpermpd|vpermq|vperm2i128|vpblendd|vpsllvd|vpsllvq|vpsrlvd|vpsrlvq|vpsravd|vblendmpd|vblendmps|vpblendmd|vpblendmq|vpblendmb|vpblendmw|vpcmpd|vpcmpud|vpcmpq|vpcmpuq|vpcmpb|vpcmpub|vpcmpw|vpcmpuw|vptestmd|vptestmq|vptestnmd|vptestnmq|vptestmb|vptestmw|vptestnmb|vptestnmw|vcompresspd|vcompressps|vpcompressd|vpcompressq|vexpandpd|vexpandps|vpexpandd|vpexpandq|vpermb|vpermw|vpermt2b|vpermt2w|vpermi2pd|vpermi2ps|vpermi2d|vpermi2q|vpermi2b|vpermi2w|vpermt2ps|vpermt2pd|vpermt2d|vpermt2q|vshuff32x4|vshuff64x2|vshuffi32x4|vshuffi64x2|vpmultishiftqb|vpternlogd|vpternlogq|vpmovqd|vpmovsqd|vpmovusqd|vpmovqw|vpmovsqw|vpmovusqw|vpmovqb|vpmovsqb|vpmovusqb|vpmovdw|vpmovsdw|vpmovusdw|vpmovdb|vpmovsdb|vpmovusdb|vpmovwb|vpmovswb|vpmovuswb|vcvtps2udq|vcvtpd2udq|vcvttps2udq|vcvttpd2udq|vcvtss2usi|vcvtsd2usi|vcvttss2usi|vcvttsd2usi|vcvtps2qq|vcvtpd2qq|vcvtps2uqq|vcvtpd2uqq|vcvttps2qq|vcvttpd2qq|vcvttps2uqq|vcvttpd2uqq|vcvtudq2ps|vcvtudq2pd|vcvtusi2ps|vcvtusi2pd|vcvtusi2sd|vcvtusi2ss|vcvtuqq2ps|vcvtuqq2pd|vcvtqq2pd|vcvtqq2ps|vgetexppd|vgetexpps|vgetexpsd|vgetexpss|vgetmantpd|vgetmantps|vgetmantsd|vgetmantss|vfixupimmpd|vfixupimmps|vfixupimmsd|vfixupimmss|vrcp14pd|vrcp14ps|vrcp14sd|vrcp14ss|vrndscaleps|vrndscalepd|vrndscaless|vrndscalesd|vrsqrt14pd|vrsqrt14ps|vrsqrt14sd|vrsqrt14ss|vscalefps|vscalefpd|vscalefss|vscalefsd|valignd|valignq|vdbpsadbw|vpabsq|vpmaxsq|vpmaxuq|vpminsq|vpminuq|vprold|vprolvd|vprolq|vprolvq|vprord|vprorvd|vprorq|vprorvq|vpscatterdd|vpscatterdq|vpscatterqd|vpscatterqq|vscatterdps|vscatterdpd|vscatterqps|vscatterqpd|vpconflictd|vpconflictq|vplzcntd|vplzcntq|vpbroadcastmb2q|vpbroadcastmw2d|vexp2pd|vexp2ps|vrcp28pd|vrcp28ps|vrcp28sd|vrcp28ss|vrsqrt28pd|vrsqrt28ps|vrsqrt28sd|vrsqrt28ss|vgatherpf0dps|vgatherpf0qps|vgatherpf0dpd|vgatherpf0qpd|vgatherpf1dps|vgatherpf1qps|vgatherpf1dpd|vgatherpf1qpd|vscatterpf0dps|vscatterpf0qps|vscatterpf0dpd|vscatterpf0qpd|vscatterpf1dps|vscatterpf1qps|vscatterpf1dpd|vscatterpf1qpd|vfpclassps|vfpclasspd|vfpclassss|vfpclasssd|vrangeps|vrangepd|vrangess|vrangesd|vreduceps|vreducepd|vreducess|vreducesd|vpmovm2d|vpmovm2q|vpmovm2b|vpmovm2w|vpmovd2m|vpmovq2m|vpmovb2m|vpmovw2m|vpmullq|vpmadd52luq|vpmadd52huq|v4fmaddps|v4fmaddss|v4fnmaddps|v4fnmaddss|vp4dpwssd|vp4dpwssds|vpdpbusd|vpdpbusds|vpdpwssd|vpdpwssds|vpcompressb|vpcompressw|vpexpandb|vpexpandw|vpshld|vpshldv|vpshrd|vpshrdv|vpopcntd|vpopcntq|vpopcntb|vpopcntw|vpshufbitqmb|gf2p8affineinvqb|gf2p8affineqb|gf2p8mulb|vpclmulqdq|vaesdec|vaesdeclast|vaesenc|vaesenclast)[ \t]/' binary.asm

CATATAN: diuji dengan gawkdan nawk.

Andriy Makukha
sumber
6

Sayangnya tidak ada utilitas yang dikenal pada tanggal ini yang mendeteksi set instruksi yang diperlukan dari executable yang diberikan.

Yang terbaik yang dapat saya sarankan untuk x86 adalah menggunakan objdump -dpada biner ELF untuk membongkar bagian yang dapat dieksekusi ke dalam bahasa Gnu Assemply ( gas). Kemudian gunakan definisi sintaks Shirkvim baik grepmelalui file kode assembly atau secara visual memindai kode assembler untuk salah satu gasOpcode_SSE41atau gasOpcode_SANDYBRIDGE_AVXinstruksi yang Anda lihat dalam gas.vimfile Shirk .

File bahasa rakitan berisi instruksi tingkat mesin ("opcodes") yang dihasilkan oleh kompiler ketika program dikompilasi. Jika program dikompilasi dengan flag waktu kompilasi untuk instruksi SSE atau AVX, dan kompiler memancarkan instruksi SSE atau AVX, maka Anda akan melihat satu atau lebih opcode SSE atau AVX dalam daftar pembongkaran yang diproduksi oleh objdump -d.

Misalnya, jika Anda melakukannya grep vroundsdbpada file kode rakitan dan menemukan kecocokan, maka Anda tahu bahwa file biner memerlukan kemampuan AVX untuk mengeksekusi.

Ada beberapa instruksi spesifik sub-arsitektur untuk x86, seperti yang dapat Anda lihat dari gas.vimfile Shirk , Jadi grepping untuk semua opcode untuk setiap sub-arsitektur akan terasa membosankan. Menulis program C, Perl atau Python untuk melakukan ini bisa menjadi ide bagus untuk proyek Open Source, terutama jika Anda dapat menemukan seseorang untuk memperpanjangnya untuk ARM, PPC dan arsitektur lainnya.

Jonathan Ben-Avraham
sumber
Apa tujuan dari gas: Saya tidak dapat menemukan program apa itu?
user2284570
@ user2284570: Saya mengedit jawaban yang terkait dengan komentar Anda. HTH.
Jonathan Ben-Avraham
Sse4.2 + AVX + 3DNOW mewakili ratusan instruksi. Butuh waktu lama untuk meluncurkan pencarian untuk masing-masing ...
user2284570
@ user2284570: Ya, saya sebutkan itu. Jika Anda perlu melakukan ini secara teratur akan lebih baik untuk menulis skrip Perl berdasarkan Shirk's gas.vim. OTOH jika ini adalah masalah sekali tembak, maka Anda dapat dengan mudah mempelajari pola opcode yang membedakan antara sub-arsitektur.
Jonathan Ben-Avraham
Saya kira perpustakaan untuk berurusan dengan opcodes akan menjadi sesuatu yang hebat untuk memulai ...
user2284570
2

Saya memberi menulis beberapa skrip utilitas python berdasarkan Jonathan Ben-Avrahams dan Kyselejsyrečeks menjawab pergi. Ini naskah kasar tetapi menyelesaikan pekerjaan.

https://gist.github.com/SleepProgger/d4f5e0a0ea2b9456e6c7ecf256629396 Secara otomatis mengunduh dan mengonversi file gas.vim dan mendukung pembuangan semua operasi yang digunakan (opsional non-dasar) termasuk fitur set dari mana asalnya. Selain itu mendukung operasi pencarian set ke fitur.

Tries to detect which CPU features where used in a given binary.

positional arguments:
  executable            The executable to analyze or the command to lookup if
                        -l is set.

optional arguments:
  -h, --help            show this help message and exit
  -j JSON_SPECS, --json-specs JSON_SPECS
                        json file containing a command to feature mapping.
  -o JSON_OUTPUT, --json-output JSON_OUTPUT
                        json file to save the command to feature mapping
                        parsed from an gas.vim file. Defaults to same folder
                        as this scipt/specs.json
  -g GAS, --gas GAS     gas.vim file to convert to feature mapping.
  -nw, --no-json-save   Do not save converted mapping from gas.vim file.
  -b, --include-base    Include base instructions in the search.
  -l, --lookup-op       Lookup arch and feature for given command. Can be
                        regex.

SleepProgger
sumber