No Linux, /proc/cpuinfo
permite verificar todos os sinalizadores de CPU que a máquina possui de maneira simples.
Normalmente, se um programa requer um superconjunto do conjunto de instruções de uma máquina, a maneira mais fácil de determinar isso é executá-lo e ver se ele gera um SIGILLsinal.
Mas no meu caso, todos os meus processadores suportam pelo menos SSE4.1 e AVX.
Então, existe uma maneira simples de verificar se um binário possui instruções especiais?
objdump --disassemble
realiza uma desmontagem. Você pode usarobjdump
para gerar uma lista de mnemônicos. Faz parte do Binutils, portanto está disponível nos sistemas GNU Linux. Além disso, as instruções adicionais podem estar presentes, mas podem não ser executadas. O programa pode ter guardas de tempo de execução.-mavx
para garantir que o compilador selecione apenas o AVX ISA, mas existem maneiras de contorná-lo. Por exemplo, o montador em linha geralmente pode evitar as verificações ISA do compilador.Respostas:
Eu iniciei um programa no Rust que tenta fazer isso. Eu acho que funciona, embora não seja documentado e muito frágil:
https://github.com/pkgw/elfx86exts
Exemplo de uso:
fonte
Eu me deparei com o mesmo problema quando estava tentando entender os processos de otimização do GCC e descobrir quais instruções foram ou não usadas durante esse processo. Como eu não sou amigável com o enorme número de códigos de operação, eu estava procurando uma maneira de visualizar instruções específicas (digamos, SSE3) dentro do código desmontado ou, pelo menos, imprimir algumas estatísticas mínimas, como se e quantas dessas instruções existem no binário.
Não encontrei nenhuma solução existente, mas a resposta de Jonathan Ben-Avraham se mostrou muito útil, pois aponta uma grande (e até parcialmente estruturada) fonte de códigos de operação. Com base nesses dados, escrevi um script Bash que pode visualizar conjuntos de instruções específicos ou imprimir estatísticas sobre eles usando
grep
quando alimentados com a saída deobjdump
.A lista de códigos de operação foi convertida em um script Bash independente, que é então incluído (com o objetivo de melhor legibilidade) no arquivo principal que eu nomeei simplesmente
opcode
. Como os opcodesgas.vim
( definições de sintaxe de Shirkvim
, da resposta de Jonathan) foram sistematicamente agrupados (aparentemente) de acordo com diferentes arquiteturas de CPU, tentei preservar essa divisão e fazer um mapeamento de conjunto de instruções architecture-> ; Agora não tenho certeza se essa foi uma boa ideia. O mapeamento não é preciso e eu até tive que fazer algumas alterações no originalgas.vim
agrupamento. Como os conjuntos de instruções relacionados à arquitetura não eram minha intenção original, tentei apenas construir conjuntos de instruções das principais arquiteturas descritas na Internet, mas sem consultar as documentações dos fabricantes. As arquiteturas AMD não parecem confiáveis para mim (exceto conjuntos de instruções como 3DNow! E SSE5). No entanto, decidi deixar aqui o código para conjuntos de instruções de várias arquiteturas para que outra pessoa examine, corrija / aprimore e dê a outros resultados experimentais.Início do arquivo principal chamado
opcode
:Um exemplo de
Opcode_list
arquivo gerado e modificado usando as instruções emopcode
27 de outubro de 2014 pode ser encontrado em http://pastebin.com/yx4rCxqs . Você pode inserir esse arquivoopcode
no lugar dasource Opcode_list
linha. Eu coloquei esse código porque o Stack Exchange não me deixou enviar uma resposta tão grande.Finalmente, o restante do
opcode
arquivo com a lógica real:Por favor, esteja ciente de que, se sua consulta de pesquisa for muito grande (por exemplo, com o conjunto de instruções Haswell e o
-r
comutador - isso inclui centenas de instruções), o cálculo pode prosseguir lentamente e demorar muito tempo em entradas grandes para as quais esse script simples não se destina. .Para informações detalhadas sobre o uso, consulte
O
opcode
script inteiro (com Opcode_list incluído) pode ser encontrado em http://pastebin.com/A8bAuHAP .Sinta-se livre para melhorar a ferramenta e corrigir quaisquer erros que eu possa ter cometido. Por fim, gostaria de agradecer a Jonathan Ben-Avraham por sua ótima idéia de usar o
gas.vim
arquivo de Shirk .EDIT: O script agora pode encontrar a qual conjunto de instruções um código de operação pertence (a expressão regular pode ser usada).
fonte
Primeiro, descompile seu binário:
Em seguida, encontre todas as instruções SSE4 no arquivo de montagem:
(Nota: o CRC32 pode corresponder aos comentários.)
Encontre as instruções mais comuns do AVX (incluindo escalares, incluindo a família AVX2, AVX-512 e algumas como FMA
vfmadd132pd
):NOTA: testado com
gawk
enawk
.fonte
Infelizmente, não parece haver nenhum utilitário conhecido até essa data que detecte o conjunto de instruções necessárias de um determinado executável.
O melhor que posso sugerir para o x86 é usar
objdump -d
no binário ELF para desmontar as seções executáveis na linguagem Gnu Assemply (gas
). Em seguida, use de Shirkvim
definições de sintaxe , quergrep
através do arquivo de código de montagem ou digitalizar visualmente o código assembler para qualquer um dosgasOpcode_SSE41
ougasOpcode_SANDYBRIDGE_AVX
instruções que você vê na de Shirkgas.vim
arquivo.O arquivo de linguagem assembly contém as instruções em nível de máquina ("opcodes") que o compilador gerou quando o programa foi compilado. Se o programa foi compilado com sinalizadores de tempo de compilação para instruções SSE ou AVX e o compilador emitiu quaisquer instruções SSE ou AVX, você deverá ver um ou mais códigos de código SSE ou AVX na lista de desmontagem produzida por
objdump -d
.Por exemplo, se você
grep vroundsdb
encontrar um arquivo de código de montagem e encontrar uma correspondência, saberá que o arquivo binário requer a execução de recursos do AVX.Existem algumas instruções específicas da subarquitetura para o x86, como você pode ver no
gas.vim
arquivo de Shirk , portanto, executargrep
ping para todos os códigos de operação para cada subarquitetura seria tedioso. Escrever um programa C, Perl ou Python para fazer isso pode ser uma excelente idéia para um projeto de código aberto, especialmente se você puder encontrar alguém para estendê-lo para ARM, PPC e outras arquiteturas.fonte
gas.vim
. OTOH, se este for um problema de uma só vez, você poderá aprender facilmente os padrões dos códigos de operação que diferenciam as sub-arquiteturas.Eu escrevi algum script utilitário python baseado nas respostas de Jonathan Ben-Avrahams e Kyselejsyrečeks. É um roteiro grosseiro, mas faz o trabalho.
https://gist.github.com/SleepProgger/d4f5e0a0ea2b9456e6c7ecf256629396 Ele baixa e converte automaticamente o arquivo gas.vim e suporta o dumping de todas as operações usadas (opcionais não básicas), incluindo o conjunto de recursos de onde vêm. Além disso, ele oferece suporte à pesquisa de conjunto de recursos.
fonte