Cách kiểm tra xem nhị phân có yêu cầu SSE4 hoặc AVX trên Linux không


19

Trên Linux, /proc/cpuinfocho phép một người kiểm tra tất cả các cờ CPU mà máy có một cách đơn giản.
Thông thường, nếu một chương trình yêu cầu siêu bộ tập lệnh của máy, cách dễ nhất để xác định điều này là chạy nó và xem liệu nó có tăng SIGILLtín hiệu hay không.

Nhưng trong trường hợp của tôi, tất cả các bộ xử lý của tôi đều hỗ trợ ít nhất SSE4.1 và AVX.
Vì vậy, có một cách đơn giản để kiểm tra xem một nhị phân có các hướng dẫn đặc biệt bên trong không?


Có thể có các trình giả lập cho phép bạn chọn tập lệnh nào được bật. QEMU hiện không hỗ trợ AVX, do đó có thể "không hoạt động" như mong đợi ở đó: superuser.com/questions/453786/how-do-i-get-avx-support-in-qemu || superuser.com/questions/548740/ từ
Ciro Santilli 改造 心 心

2
objdump --disassemblethực hiện tháo gỡ. Bạn có thể sử dụng objdumpđể tạo một danh sách ghi nhớ. Nó là một phần của Binutils, vì vậy nó có sẵn trên các hệ thống GNU Linux. Ngoài ra, các hướng dẫn bổ sung có thể có mặt nhưng có thể không được thực thi. Chương trình có thể có bộ bảo vệ thời gian chạy.
jww

@jww: heemm, vâng, nhưng tôi bận tâm về việc có một chương trình thực thi chạy ở mọi nơi, không phải về việc học hơn 600 opcodes để lập trình lắp ráp.
dùng2284570

Chà, bạn phải học những gì bạn có thể (và không thể) sử dụng. Đó là trách nhiệm của bạn. Tôi cho rằng bạn có thể biên dịch -mavxđể đảm bảo trình biên dịch chỉ chọn từ AVX ISA, nhưng có nhiều cách để vượt qua nó. Ví dụ, trình biên dịch mã nội tuyến thường có thể vượt qua các kiểm tra ISA của trình biên dịch.
jww

@jww: và nếu nhị phân là một nguồn đóng (theo nghĩa mã nguồn bị xóa sau khi xây dựng) đối tượng chia sẻ được xây dựng bởi một tập lệnh / trình biên dịch độc quyền?
dùng2284570

Câu trả lời:


11

Tôi đã đập ra một chương trình ở Rust cố gắng làm điều này. Tôi nghĩ rằng nó hoạt động, mặc dù nó không có giấy tờ và rất mong manh:

https://github.com/pkgw/elfx86exts

Ví dụ sử dụng:

$ 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

Tôi đã thử chạy nó trên libtensorflow.so (sha224: 8f665acf0f455d5056014dfa2d48c22ab6cf83eb073842e8304878d0) từ gói này (phiên bản: 1.8.0-5) và nó đóng băng toàn bộ máy tính của tôi.
Philippe

@Philippe Vui lòng gửi một vấn đề trên GitHub! Đó là nơi tốt hơn để thảo luận về các chủ đề như vậy, tôi nghĩ.
Peter

Ok, tôi đã tạo ra một vấn đề trên github của bạn.
Philippe

18

Tôi đã gặp phải vấn đề tương tự khi tôi đang cố gắng tìm hiểu các quy trình tối ưu hóa GCC và tìm hiểu những hướng dẫn nào đã hoặc chưa được sử dụng trong quá trình này. Vì tôi không thân thiện với số lượng mã hoạt động khổng lồ, tôi đã tìm cách để trực quan hóa các hướng dẫn cụ thể (giả sử SSE3) trong mã được tháo rời hoặc ít nhất là in một số thống kê tối thiểu như liệu có bao nhiêu hướng dẫn này không trong nhị phân.

Tôi chưa tìm thấy bất kỳ giải pháp hiện có nào, nhưng câu trả lời của Jonathan Ben-Avraham tỏ ra rất hữu ích, vì nó chỉ ra một nguồn mã hoạt động tuyệt vời (và thậm chí có cấu trúc một phần). Dựa trên dữ liệu này, tôi đã viết một tập lệnh Bash có thể trực quan hóa các tập lệnh cụ thể hoặc in số liệu thống kê về chúng bằng cách sử dụng grepkhi được cung cấp với đầu ra từ objdump.

Danh sách mã hoạt động đã được chuyển đổi thành tập lệnh Bash độc lập, sau đó được đưa vào (với mục đích dễ đọc hơn) trong tệp chính mà tôi đã đặt tên đơn giản opcode. Vì các mã trong gas.vim( định nghĩa cú pháp của Shirkvim , từ câu trả lời của Jonathan) được nhóm lại một cách có hệ thống (dường như) theo các kiến ​​trúc CPU khác nhau, tôi đã cố gắng duy trì phân chia này và tạo ánh xạ tập lệnh- > ; Tôi không chắc bây giờ liệu đó có phải là một ý tưởng tốt hay không. Ánh xạ không chính xác và tôi thậm chí phải thực hiện một số thay đổi trong bản gốcgas.vimphân nhóm. Vì các tập lệnh liên quan đến kiến ​​trúc không phải là mục đích ban đầu của tôi, tôi chỉ cố gắng xây dựng các tập lệnh của các kiến ​​trúc chính được mô tả trên Internet, nhưng không có tài liệu của nhà sản xuất tư vấn. Các kiến ​​trúc AMD dường như không đáng tin cậy đối với tôi (ngoại trừ các bộ hướng dẫn như 3DNow! Và SSE5). Tuy nhiên, tôi quyết định để lại mã cho các bộ hướng dẫn của các kiến ​​trúc khác nhau ở đây để người khác kiểm tra và sửa chữa / cải thiện và cung cấp cho người khác một số kết quả dự kiến.

Bắt đầu tập tin chính có tên 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"

Có thể tìm thấy một ví dụ về một Opcode_listtệp được tạo và sửa đổi bằng cách sử dụng các hướng dẫn vào opcodengày 27 tháng 10 năm 2014 tại http://pastebin.com/yx4rCxqs . Bạn có thể chèn tệp này ngay vào opcodevị trí của source Opcode_listdòng. Tôi đã đặt mã này ra vì Stack Exchange sẽ không cho phép tôi gửi một câu trả lời lớn như vậy.

Cuối cùng, phần còn lại của opcodetệp với logic thực tế:

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

Xin lưu ý rằng nếu truy vấn tìm kiếm của bạn quá lớn (ví dụ: với tập lệnh Haswell và công -rtắc - bao gồm hàng trăm hướng dẫn), việc tính toán có thể tiến hành chậm và mất nhiều thời gian cho các đầu vào lớn mà tập lệnh đơn giản này không dành cho .

Để biết thông tin chi tiết về tư vấn sử dụng

./opcode -h

opcodethể tìm thấy toàn bộ tập lệnh (bao gồm Opcode_list) tại http://pastebin.com/A8bAuHAP .

Vui lòng cải thiện công cụ và sửa chữa bất kỳ sai lầm nào tôi có thể đã mắc phải. Cuối cùng, tôi muốn cảm ơn Jonathan Ben-Avraham vì ý tưởng tuyệt vời của anh ấy về việc sử dụng gas.vimtập tin của Shirk .

EDIT: Tập lệnh hiện có thể tìm thấy tập lệnh nào đặt mã thao tác (có thể sử dụng biểu thức chính quy).


9

Đầu tiên, dịch ngược nhị phân của bạn:

objdump -d binary > binary.asm

Sau đó tìm tất cả các hướng dẫn SSE4 trong tệp lắp ráp:

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

(Lưu ý: CRC32 có thể phù hợp với ý kiến.)

Tìm các hướng dẫn AVX phổ biến nhất (bao gồm cả vô hướng, bao gồm AVX2, họ AVX-512 và một số FMA như 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

LƯU Ý: đã thử nghiệm với gawknawk.


6

Thật không may, dường như không có bất kỳ tiện ích nổi tiếng nào kể từ ngày này phát hiện ra tập lệnh được yêu cầu từ một tệp thực thi nhất định.

Điều tốt nhất mà tôi có thể đề xuất cho x86 là sử dụng objdump -dtrên tệp nhị phân ELF để phân tách các phần thực thi thành ngôn ngữ Gnu Assemply ( gas). Sau đó, sử dụng các định nghĩa cú pháp của Shirkvim để grepthông qua tệp mã lắp ráp hoặc quét trực quan mã trình biên dịch mã để tìm bất kỳ gasOpcode_SSE41hoặc các gasOpcode_SANDYBRIDGE_AVXhướng dẫn mà bạn thấy trong gas.vimtệp của Shirk .

Tệp ngôn ngữ lắp ráp chứa các hướng dẫn cấp độ máy ("opcodes") mà trình biên dịch tạo ra khi chương trình được biên dịch. Nếu chương trình được biên dịch với các cờ thời gian biên dịch cho các lệnh SSE hoặc AVX và trình biên dịch đã phát ra bất kỳ lệnh SSE hoặc AVX nào, thì bạn sẽ thấy một hoặc nhiều opc SSE hoặc AVX trong danh sách phân tách được tạo bởi objdump -d.

Ví dụ: nếu bạn thực hiện grep vroundsdbtrên tệp mã lắp ráp và tìm thấy sự trùng khớp, thì bạn biết rằng tệp nhị phân yêu cầu các khả năng AVX để thực thi.

Có khá nhiều hướng dẫn dành riêng cho kiến ​​trúc phụ cho x86, như bạn có thể thấy từ gas.vimtệp của Shirk , vì vậy grepping cho tất cả các opcode cho mỗi kiến ​​trúc phụ sẽ phải tẻ nhạt. Viết chương trình C, Perl hoặc Python để làm điều này có thể là một ý tưởng tuyệt vời cho một dự án Nguồn mở, đặc biệt là nếu bạn có thể tìm ai đó mở rộng nó cho ARM, PPC và các kiến ​​trúc khác.


Mục đích của khí là gì: Tôi không thể tìm thấy chương trình đó là gì?
dùng2284570

@ user2284570: Tôi đã chỉnh sửa câu trả lời liên quan đến nhận xét của bạn. HTH.
Jonathan Ben-Avraham

Sse4.2 + AVX + 3DNOW đại diện cho hàng trăm hướng dẫn. Sẽ mất nhiều thời gian để khởi chạy một tìm kiếm cho mỗi người trong số họ ...
user2284570

@ user2284570: Vâng, tôi đã đề cập đến điều đó. Nếu bạn cần làm điều này thường xuyên, tốt hơn là viết một kịch bản Perl dựa trên Shirk gas.vim. OTOH nếu đây là sự cố một lần, thì bạn có thể dễ dàng tìm hiểu mô hình của các opcodes phân biệt giữa các kiến ​​trúc phụ.
Jonathan Ben-Avraham

Tôi đoán rằng một thư viện để xử lý các opcodes sẽ là một cái gì đó tuyệt vời để bắt đầu ...
user2284570

2

Tôi đã viết một số kịch bản tiện ích python dựa trên câu trả lời của Jonathan Ben-Avrahams và Kyselejsyrečeks. Đó là một kịch bản thô thiển nhưng hoàn thành công việc.

https://gist.github.com/S ngủProgger / d4f5e0a0ea2b9456e6c7ecf256629394 Nó tự động tải xuống và chuyển đổi tệp gas.vim và hỗ trợ loại bỏ tất cả các hoạt động được sử dụng (không cơ bản tùy chọn) bao gồm cả bộ tính năng mà chúng đến từ. Ngoài ra, nó hỗ trợ op để thiết lập tính năng tra cứu.

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.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.