วิธีตรวจสอบว่าไบนารีต้องการ SSE4 หรือ AVX บน Linux


20

บน Linux /proc/cpuinfoอนุญาตให้หนึ่งตรวจสอบการตั้งค่าสถานะ CPU ทั้งหมดที่เครื่องมีในวิธีที่ง่าย
โดยปกติแล้วหากโปรแกรมต้องการชุดคำสั่งของเครื่องวิธีที่ง่ายที่สุดในการพิจารณาว่าจะรันหรือไม่และดูว่าSIGILLสัญญาณเพิ่มขึ้นหรือไม่

แต่ในกรณีของฉันโปรเซสเซอร์ทั้งหมดของฉันสนับสนุนอย่างน้อย SSE4.1 และ AVX
ดังนั้นมีวิธีง่ายๆในการตรวจสอบว่าไบนารีมีคำแนะนำพิเศษภายใน?


อาจมีอีมูเลเตอร์ซึ่งให้คุณเลือกชุดคำสั่งที่เปิดใช้งาน QEMU ไม่สนับสนุน AVX ดังนั้นอาจจะบอกว่า "ไม่ทำงาน" ตามที่คาดไว้ที่นั่นsuperuser.com/questions/453786/how-do-i-get-avx-support-in-qemu || superuser.com/questions/548740/…
Ciro Santilli 新疆改造中心法轮功六四事件

2
objdump --disassembleทำการถอดชิ้นส่วน คุณสามารถใช้objdumpเพื่อสร้างรายการช่วยจำ มันเป็นส่วนหนึ่งของ Binutils ดังนั้นมันจึงมีอยู่ในระบบ GNU Linux นอกจากนี้อาจมีคำแนะนำเพิ่มเติม แต่ไม่สามารถดำเนินการได้ โปรแกรมอาจมียามรันไทม์
jww

@ jww: เฮ่มใช่ แต่ฉันกังวลเกี่ยวกับการใช้งานได้ทุกหนทุกแห่งไม่เกี่ยวกับการเรียนรู้มากกว่า 600 opcode เพื่อโปรแกรมในการชุมนุม
user2284570

คุณต้องเรียนรู้สิ่งที่คุณสามารถใช้ (และไม่สามารถ) ได้ นั่นคือความรับผิดชอบของคุณ ฉันคิดว่าคุณสามารถคอมไพล์ด้วย-mavxเพื่อให้แน่ใจว่าคอมไพเลอร์เลือกเฉพาะจาก AVX ISA แต่มีวิธีหลีกเลี่ยงมัน ยกตัวอย่างเช่นอินไลน์แอสเซมเบลอร์มักจะเลี่ยงขั้นตอนการตรวจสอบ ISA ของคอมไพเลอร์
jww

@ jww: และถ้าไบนารีเป็นแหล่งปิด(ในความรู้สึกซอร์สโค้ดถูกลบหลังจากการสร้าง)วัตถุที่ใช้ร่วมกันสร้างโดยสคริปต์กรรมสิทธิ์ / คอมไพเลอร์?
2284570

คำตอบ:


11

ฉันกระแทกโปรแกรมใน Rust ที่พยายามทำสิ่งนี้ ฉันคิดว่ามันใช้งานได้แม้ว่ามันจะไม่มีเอกสารและบอบบางมาก

https://github.com/pkgw/elfx86exts

ตัวอย่างการใช้งาน:

$ 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

ฉันพยายามเรียกใช้บน libtensorflow.so (sha224: 8f665acf0f455d5056014dfa2d48c22ab6cf83eb073842e8304878d0) จากแพ็คเกจนี้ (คอมพิวเตอร์: รุ่น 1.8.0-5)
ฟิลิปป์

@Philippe กรุณายื่นปัญหาใน GitHub! ฉันคิดว่านั่นเป็นเรื่องที่ดีกว่า
Peter

ตกลงฉันได้สร้างปัญหาบน GitHub ของคุณ
ฟิลิปป์

18

ฉันชนกับปัญหาเดียวกันเมื่อฉันพยายามที่จะเข้าใจกระบวนการเพิ่มประสิทธิภาพ GCC และค้นหาคำสั่งที่มีหรือไม่ได้ใช้ในระหว่างกระบวนการนี้ เนื่องจากฉันไม่เป็นมิตรกับรหัสการทำงานจำนวนมากฉันจึงมองหาวิธีการแสดงภาพคำแนะนำเฉพาะ (สมมติว่า SSE3) ภายในรหัสที่ถอดแยกชิ้นส่วนหรืออย่างน้อยพิมพ์สถิติขั้นต่ำบางอย่างเช่นและมีคำแนะนำเหล่านี้กี่วิธี ในไบนารี

ฉันไม่พบวิธีแก้ปัญหาใด ๆ ที่มีอยู่ แต่คำตอบของ Jonathan Ben-Avraham ได้รับการพิสูจน์แล้วว่ามีประโยชน์มากเพราะมันชี้ให้เห็นถึงรหัสการดำเนินการที่ดีเยี่ยม (และมีโครงสร้างบางส่วน) จากข้อมูลนี้ฉันได้เขียนสคริปต์ Bash ซึ่งสามารถมองเห็นชุดคำสั่งเฉพาะหรือพิมพ์สถิติเกี่ยวกับพวกเขาโดยใช้grepobjdumpเมื่อเลี้ยงกับการส่งออกจาก

รายการของรหัสการดำเนินการที่ได้รับการดัดแปลงให้เป็นแบบสแตนด์อโลนสคริปต์ทุบตีซึ่งรวมแล้ว (สำหรับวัตถุประสงค์ของการอ่านที่ดีกว่า) opcodeในไฟล์หลักที่ผมได้ตั้งชื่อเพียง ตั้งแต่ opcodes ในgas.vim( คำจำกัดความไวยากรณ์ของ Shirkvimจากคำตอบของ Jonathan) ถูกจัดกลุ่มอย่างเป็นระบบ (ดูเหมือน) ตามสถาปัตยกรรมซีพียูที่แตกต่างกันฉันพยายามที่จะรักษาส่วนนี้และสร้างการแมปชุดสถาปัตยกรรม -> ชุดคำสั่ง ตอนนี้ฉันไม่แน่ใจว่าเป็นความคิดที่ดีหรือไม่ การทำแผนที่ไม่ถูกต้องและฉันต้องเปลี่ยนแปลงบางอย่างในต้นฉบับgas.vimการจัดกลุ่ม เนื่องจากชุดคำสั่งที่เกี่ยวข้องกับสถาปัตยกรรมไม่ใช่ความตั้งใจดั้งเดิมของฉันฉันจึงพยายามสร้างชุดคำสั่งของสถาปัตยกรรมสำคัญ ๆ ที่อธิบายไว้บนอินเทอร์เน็ต แต่ไม่มีการให้คำปรึกษาด้านเอกสารของผู้ผลิต สถาปัตยกรรม AMD ไม่น่าเชื่อถือสำหรับฉันเลย (ยกเว้นชุดคำสั่งเช่น 3DNow! และ SSE5) อย่างไรก็ตามฉันตัดสินใจทิ้งรหัสไว้สำหรับชุดคำสั่งของสถาปัตยกรรมต่าง ๆ ที่นี่เพื่อให้คนอื่นตรวจสอบและแก้ไข / ปรับปรุงและเพื่อให้คนอื่นได้ผลลัพธ์เบื้องต้น

จุดเริ่มต้นของไฟล์หลักชื่อ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"

ตัวอย่างของOpcode_listไฟล์ที่สร้างและแก้ไขโดยใช้คำแนะนำในopcodeขณะที่ 27 ตุลาคม 2014, สามารถพบได้ที่http://pastebin.com/yx4rCxqs คุณสามารถแทรกไฟล์นี้ลงopcodeในตำแหน่งของsource Opcode_listบรรทัด ฉันใส่รหัสนี้ออกเพราะการแลกเปลี่ยนแบบสแต็คจะไม่ให้ฉันส่งคำตอบที่มีขนาดใหญ่เช่นนี้

สุดท้ายส่วนที่เหลือของopcodeไฟล์ด้วยตรรกะจริง:

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

โปรดทราบว่าหากคำค้นหาของคุณใหญ่เกินไป (เช่นชุดคำสั่ง Haswell และ -rสวิตช์ - ซึ่งมีคำแนะนำหลายร้อยคำ) การคำนวณอาจดำเนินการช้าและใช้เวลานานสำหรับอินพุตขนาดใหญ่ซึ่งสคริปต์แบบง่ายนี้ไม่ได้มีไว้สำหรับ .

สำหรับข้อมูลรายละเอียดเกี่ยวกับการใช้งานให้คำปรึกษา

./opcode -h

สามารถดูopcodeสคริปต์ทั้งหมด(พร้อม Opcode_list) ได้ที่http://pastebin.com/A8bAuHAP http://pastebin.com/A8bAuHAP

โปรดปรับปรุงเครื่องมือและแก้ไขข้อผิดพลาดใด ๆ ที่ฉันอาจทำ สุดท้ายนี้ฉันขอขอบคุณ Jonathan Ben-Avraham สำหรับแนวคิดที่ยอดเยี่ยมของเขาในการใช้gas.vimไฟล์ของ Shirk

แก้ไข:สคริปต์ตอนนี้สามารถหาคำสั่งที่ตั้งรหัสการดำเนินการเป็นของ (สามารถใช้การแสดงออกปกติ)


9

ขั้นแรกให้ถอดรหัสไบนารีของคุณ:

objdump -d binary > binary.asm

จากนั้นค้นหาคำแนะนำ SSE4 ทั้งหมดในไฟล์ชุดประกอบ:

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

(หมายเหตุ: CRC32 อาจตรงกับความคิดเห็น)

ค้นหาคำแนะนำ AVX ที่พบบ่อยที่สุด (รวมถึงสเกลาร์รวมถึงตระกูล AVX2, AVX-512 และ 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

หมายเหตุ: การทดสอบกับและgawknawk


6

น่าเสียดายที่ไม่มียูทิลิตี้ที่รู้จักกันดี ณ วันนี้ซึ่งตรวจพบชุดคำสั่งที่จำเป็นจากชุดปฏิบัติการที่ให้มา

ที่ดีที่สุดที่ฉันสามารถแนะนำสำหรับ x86 คือการใช้objdump -dบนไบนารีเอลฟ์เพื่อแยกส่วนที่ปฏิบัติการได้เป็นภาษา Gnu Assemply ( gas) จากนั้นใช้คำจำกัดความทางไวยากรณ์ของ Shirkvimเพื่อดูgrepไฟล์รหัสประกอบหรือสแกนรหัสแอสเซมเบลอร์ด้วยวิธีใด ๆgasOpcode_SSE41หรือgasOpcode_SANDYBRIDGE_AVXคำแนะนำที่คุณเห็นใน Shirk'sgas.vimไฟล์

ไฟล์ภาษาแอสเซมบลีประกอบด้วยคำแนะนำระดับเครื่อง ("opcodes") ที่คอมไพเลอร์สร้างขึ้นเมื่อโปรแกรมถูกคอมไพล์ หากโปรแกรมที่ถูกรวบรวมกับธงรวบรวมเวลาสำหรับ SSE หรือ AVX คำแนะนำและคอมไพเลอร์ที่ปล่อยออกมาใด ๆ SSE หรือ AVX คำแนะนำแล้วคุณจะเห็นหนึ่งหรือมากกว่าหนึ่ง SSE หรือ AVX opcodes ใน dissassembly objdump -dในรายการที่ผลิตโดย

ตัวอย่างเช่นหากคุณทำgrep vroundsdbในไฟล์รหัสแอสเซมบลีและค้นหาคู่ที่ตรงกันคุณรู้ว่าไฟล์ไบนารีต้องการความสามารถ AVX ในการดำเนินการ

มีคำแนะนำเฉพาะสถาปัตยกรรมย่อยจำนวนเล็กน้อยสำหรับ x86 อย่างที่คุณเห็นจากgas.vimไฟล์ของ Shirk ดังนั้นการgrepping สำหรับ opcodes ทั้งหมดสำหรับแต่ละ sub-architecture นั้นน่าเบื่อ การเขียนโปรแกรม C, Perl หรือ Python เพื่อทำสิ่งนี้อาจเป็นแนวคิดที่ยอดเยี่ยมสำหรับโครงการโอเพนซอร์ซโดยเฉพาะอย่างยิ่งถ้าคุณสามารถหาคนที่จะขยายมันสำหรับ ARM, PPC และสถาปัตยกรรมอื่น ๆ


จุดประสงค์ของแก๊สคืออะไร: ฉันไม่พบโปรแกรมนั้น
2284570

@ user2284570: ฉันได้แก้ไขคำตอบที่เกี่ยวข้องกับความคิดเห็นของคุณ HTH
Jonathan Ben-Avraham

Sse4.2 + AVX + 3DNOW แสดงคำสั่งหลายร้อยคำ ใช้เวลานานในการเริ่มค้นหาแต่ละรายการ ...
2284570

@ user2284570: ใช่ฉันพูดถึงแล้ว หากคุณจำเป็นต้องทำเช่นนี้เป็นประจำก็จะดีกว่าที่จะเขียนสคริปต์ Perl gas.vimบนพื้นฐานของการปัดของ OTOH ถ้านี่เป็นปัญหาแบบครั้งเดียวคุณสามารถเรียนรู้รูปแบบของ opcode ที่แยกความแตกต่างระหว่างสถาปัตยกรรมย่อยได้อย่างง่ายดาย
Jonathan Ben-Avraham

ฉันเดาห้องสมุดสำหรับจัดการกับ opcodes จะเป็นสิ่งที่ดีสำหรับการเริ่มต้น ...
user2284570

2

ฉันเขียนสคริปต์ยูทิลิตี้หลามตาม Jonathan Ben-Avrahams และKyselejsyrečeks มันเป็นสคริปต์ที่หยาบคาย แต่ทำงานเสร็จแล้ว

https://gist.github.com/SleepProgger/d4f5e0a0ea2b9456e6c7ecf256629396 มันจะดาวน์โหลดและแปลงไฟล์ gas.vim โดยอัตโนมัติและรองรับการถ่ายโอนข้อมูลที่ใช้แล้วทั้งหมด (รวมถึงคุณสมบัติที่ไม่ได้ตั้งค่า) นอกจากนี้ยังรองรับการค้นหา op to Feature set

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.

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.